@@ -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