@@ -7,17 +7,20 @@ messages during compilation.
77
88A lint check names a potentially undesirable coding pattern, such as
99unreachable code or omitted documentation. The lint attributes ` allow ` ,
10- ` warn ` , ` deny ` , and ` forbid ` use the [ _ MetaListPaths_ ] syntax to specify a
11- list of lint names to change the lint level for the entity to which the
12- attribute applies.
10+ ` expect ` , ` warn ` , ` deny ` , and ` forbid ` use the [ _ MetaListPaths_ ] syntax
11+ to specify a list of lint names to change the lint level for the entity
12+ to which the attribute applies.
1313
1414For any lint check ` C ` :
1515
16- * ` allow(C) ` overrides the check for ` C ` so that violations will go
17- unreported,
18- * ` warn(C) ` warns about violations of ` C ` but continues compilation.
19- * ` deny(C) ` signals an error after encountering a violation of ` C ` ,
20- * ` forbid(C) ` is the same as ` deny(C) ` , but also forbids changing the lint
16+ * ` #[allow(C)] ` overrides the check for ` C ` so that violations will go
17+ unreported.
18+ * ` #[expect(C)] ` indicates that lint ` C ` is expected to be emitted. The
19+ attribute will suppress the emission of ` C ` or issue a warning, if the
20+ expectation is unfulfilled.
21+ * ` #[warn(C)] ` warns about violations of ` C ` but continues compilation.
22+ * ` #[deny(C)] ` signals an error after encountering a violation of ` C ` ,
23+ * ` #[forbid(C)] ` is the same as ` deny(C) ` , but also forbids changing the lint
2124 level afterwards,
2225
2326> Note: The lint checks supported by ` rustc ` can be found via ` rustc -W help ` ,
@@ -66,8 +69,8 @@ pub mod m2 {
6669}
6770```
6871
69- This example shows how one can use ` forbid ` to disallow uses of ` allow ` for
70- that lint check:
72+ This example shows how one can use ` forbid ` to disallow uses of ` allow ` or
73+ ` expect ` for that lint check:
7174
7275``` rust,compile_fail
7376#[forbid(missing_docs)]
@@ -83,6 +86,124 @@ pub mod m3 {
8386> [ command-line] [ rustc-lint-cli ] , and also supports [ setting
8487> caps] [ rustc-lint-caps ] on the lints that are reported.
8588
89+ ### Lint Reasons
90+
91+ All lint attributes support an additional ` reason ` parameter, to give context why
92+ a certain attribute was added. This reason will be displayed as part of the lint
93+ message if the lint is emitted at the defined level.
94+
95+ ``` rust,edition2015,compile_fail
96+ // `keyword_idents` is allowed by default. Here we deny it to
97+ // avoid migration of identifiers when we update the edition.
98+ #![deny(
99+ keyword_idents,
100+ reason = "we want to avoid these idents to be future compatible"
101+ )]
102+
103+ // This name was allowed in Rust's 2015 edition. We still aim to avoid
104+ // this to be future compatible and not confuse end users.
105+ fn dyn() {}
106+ ```
107+
108+ Here is another example, where the lint is allowed with a reason:
109+
110+ ``` rust
111+ use std :: path :: PathBuf ;
112+
113+ pub fn get_path () -> PathBuf {
114+ // The `reason` parameter on `allow` attributes acts as documentation for the reader.
115+ #[allow(unused_mut, reason = " this is only modified on some platforms" )]
116+ let mut file_name = PathBuf :: from (" git" );
117+
118+ #[cfg(target_os = " windows" )]
119+ file_name . set_extension (" exe" );
120+
121+ file_name
122+ }
123+ ```
124+
125+ ### The ` #[expect] ` attribute
126+
127+ The ` #[expect(C)] ` attribute creates a lint expectation for lint ` C ` . The
128+ expectation will be fulfilled, if a ` #[warn(C)] ` attribute at the same location
129+ would result in a lint emission. If the expectation is unfulfilled, because
130+ lint ` C ` would not be emitted, the ` unfulfilled_lint_expectations ` lint will
131+ be emitted at the attribute.
132+
133+ ``` rust
134+ fn main () {
135+ // This `#[expect]` attribute creates a lint expectation, that the `unused_variables`
136+ // lint would be emitted by the following statement. This expectation is
137+ // unfulfilled, since the `question` variable is used by the `println!` macro.
138+ // Therefore, the `unfulfilled_lint_expectations` lint will be emitted at the
139+ // attribute.
140+ #[expect(unused_variables)]
141+ let question = " who lives in a pineapple under the sea?" ;
142+ println! (" {question}" );
143+
144+ // This `#[expect]` attribute creates a lint expectation that will be fulfilled, since
145+ // the `answer` variable is never used. The `unused_variables` lint, that would usually
146+ // be emitted, is suppressed. No warning will be issued for the statement or attribute.
147+ #[expect(unused_variables)]
148+ let answer = " SpongeBob SquarePants!" ;
149+ }
150+ ```
151+
152+ The lint expectation is only fulfilled by lint emissions which have been suppressed by
153+ the ` expect ` attribute. If the lint level is modified in the scope with other level
154+ attributes like ` allow ` or ` warn ` , the lint emission will be handled accordingly and the
155+ expectation will remain unfulfilled.
156+
157+ ``` rust
158+ #[expect(unused_variables)]
159+ fn select_song () {
160+ // This will emit the `unused_variables` lint at the warn level
161+ // as defined by the `warn` attribute. This will not fulfill the
162+ // expectation above the function.
163+ #[warn(unused_variables)]
164+ let song_name = " Crab Rave" ;
165+
166+ // The `allow` attribute suppresses the lint emission. This will not
167+ // fulfill the expectation as it has been suppressed by the `allow`
168+ // attribute and not the `expect` attribute above the function.
169+ #[allow(unused_variables)]
170+ let song_creator = " Noisestorm" ;
171+
172+ // This `expect` attribute will suppress the `unused_variables` lint emission
173+ // at the variable. The `expect` attribute above the function will still not
174+ // be fulfilled, since this lint emission has been suppressed by the local
175+ // expect attribute.
176+ #[expect(unused_variables)]
177+ let song_version = " Monstercat Release" ;
178+ }
179+ ```
180+
181+ If the ` expect ` attribute contains several lints, each one is expected separately. For a
182+ lint group it's enough if one lint inside the group has been emitted:
183+
184+ ``` rust
185+ // This expectation will be fulfilled by the unused value inside the function
186+ // since the emitted `unused_variables` lint is inside the `unused` lint group.
187+ #[expect(unused)]
188+ pub fn thoughts () {
189+ let unused = " I'm running out of examples" ;
190+ }
191+
192+ pub fn another_example () {
193+ // This attribute creates two lint expectations. The `unused_mut` lint will be
194+ // suppressed and with that fulfill the first expectation. The `unused_variables`
195+ // wouldn't be emitted, since the variable is used. That expectation will therefore
196+ // be unsatisfied, and a warning will be emitted.
197+ #[expect(unused_mut, unused_variables)]
198+ let mut link = " https://www.rust-lang.org/" ;
199+
200+ println! (" Welcome to our community: {link}" );
201+ }
202+ ```
203+
204+ > Note: The behavior of ` #[expect(unfulfilled_lint_expectations)] ` is currently
205+ > defined to always generate the ` unfulfilled_lint_expectations ` lint.
206+
86207### Lint groups
87208
88209Lints may be organized into named groups so that the level of related lints
0 commit comments