1
1
use crate :: core:: dependency:: DepKind ;
2
2
use crate :: core:: FeatureValue :: Dep ;
3
- use crate :: core:: { Edition , FeatureValue , Package } ;
3
+ use crate :: core:: { Edition , Feature , FeatureValue , Features , Package } ;
4
4
use crate :: util:: interning:: InternedString ;
5
5
use crate :: { CargoResult , GlobalContext } ;
6
6
use annotate_snippets:: { Level , Snippet } ;
@@ -13,10 +13,10 @@ use std::path::Path;
13
13
use toml_edit:: ImDocument ;
14
14
15
15
fn get_span ( document : & ImDocument < String > , path : & [ & str ] , get_value : bool ) -> Option < Range < usize > > {
16
- let mut table = document. as_item ( ) . as_table_like ( ) . unwrap ( ) ;
16
+ let mut table = document. as_item ( ) . as_table_like ( ) ? ;
17
17
let mut iter = path. into_iter ( ) . peekable ( ) ;
18
18
while let Some ( key) = iter. next ( ) {
19
- let ( key, item) = table. get_key_value ( key) . unwrap ( ) ;
19
+ let ( key, item) = table. get_key_value ( key) ? ;
20
20
if iter. peek ( ) . is_none ( ) {
21
21
return if get_value {
22
22
item. span ( )
@@ -82,6 +82,7 @@ pub struct Lint {
82
82
pub groups : & ' static [ LintGroup ] ,
83
83
pub default_level : LintLevel ,
84
84
pub edition_lint_opts : Option < ( Edition , LintLevel ) > ,
85
+ pub feature_gate : Option < & ' static Feature > ,
85
86
}
86
87
87
88
impl Lint {
@@ -90,7 +91,17 @@ impl Lint {
90
91
pkg_lints : & TomlToolLints ,
91
92
ws_lints : Option < & TomlToolLints > ,
92
93
edition : Edition ,
94
+ unstable_features : & Features ,
93
95
) -> ( LintLevel , LintLevelReason ) {
96
+ // We should return `Allow` if a lint is behind a feature, but it is
97
+ // not enabled, that way the lint does not run.
98
+ if self
99
+ . feature_gate
100
+ . is_some_and ( |f| !unstable_features. is_enabled ( f) )
101
+ {
102
+ return ( LintLevel :: Allow , LintLevelReason :: Default ) ;
103
+ }
104
+
94
105
self . groups
95
106
. iter ( )
96
107
. map ( |g| {
@@ -164,7 +175,7 @@ impl From<TomlLintLevel> for LintLevel {
164
175
}
165
176
}
166
177
167
- #[ derive( Copy , Clone , Debug ) ]
178
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
168
179
pub enum LintLevelReason {
169
180
Default ,
170
181
Edition ( Edition ) ,
@@ -228,6 +239,7 @@ const IM_A_TEAPOT: Lint = Lint {
228
239
groups : & [ TEST_DUMMY_UNSTABLE ] ,
229
240
default_level : LintLevel :: Allow ,
230
241
edition_lint_opts : None ,
242
+ feature_gate : Some ( Feature :: test_dummy_unstable ( ) ) ,
231
243
} ;
232
244
233
245
pub fn check_im_a_teapot (
@@ -239,7 +251,13 @@ pub fn check_im_a_teapot(
239
251
gctx : & GlobalContext ,
240
252
) -> CargoResult < ( ) > {
241
253
let manifest = pkg. manifest ( ) ;
242
- let ( lint_level, reason) = IM_A_TEAPOT . level ( pkg_lints, ws_lints, manifest. edition ( ) ) ;
254
+ let ( lint_level, reason) = IM_A_TEAPOT . level (
255
+ pkg_lints,
256
+ ws_lints,
257
+ manifest. edition ( ) ,
258
+ manifest. unstable_features ( ) ,
259
+ ) ;
260
+
243
261
if lint_level == LintLevel :: Allow {
244
262
return Ok ( ( ) ) ;
245
263
}
@@ -295,6 +313,7 @@ const IMPLICIT_FEATURES: Lint = Lint {
295
313
groups : & [ ] ,
296
314
default_level : LintLevel :: Allow ,
297
315
edition_lint_opts : None ,
316
+ feature_gate : None ,
298
317
} ;
299
318
300
319
pub fn check_implicit_features (
@@ -305,19 +324,20 @@ pub fn check_implicit_features(
305
324
error_count : & mut usize ,
306
325
gctx : & GlobalContext ,
307
326
) -> CargoResult < ( ) > {
308
- let edition = pkg. manifest ( ) . edition ( ) ;
327
+ let manifest = pkg. manifest ( ) ;
328
+ let edition = manifest. edition ( ) ;
309
329
// In Edition 2024+, instead of creating optional features, the dependencies are unused.
310
330
// See `UNUSED_OPTIONAL_DEPENDENCY`
311
331
if edition >= Edition :: Edition2024 {
312
332
return Ok ( ( ) ) ;
313
333
}
314
334
315
- let ( lint_level, reason) = IMPLICIT_FEATURES . level ( pkg_lints, ws_lints, edition) ;
335
+ let ( lint_level, reason) =
336
+ IMPLICIT_FEATURES . level ( pkg_lints, ws_lints, edition, manifest. unstable_features ( ) ) ;
316
337
if lint_level == LintLevel :: Allow {
317
338
return Ok ( ( ) ) ;
318
339
}
319
340
320
- let manifest = pkg. manifest ( ) ;
321
341
let activated_opt_deps = manifest
322
342
. resolved_toml ( )
323
343
. features ( )
@@ -373,6 +393,7 @@ const UNUSED_OPTIONAL_DEPENDENCY: Lint = Lint {
373
393
groups : & [ ] ,
374
394
default_level : LintLevel :: Warn ,
375
395
edition_lint_opts : None ,
396
+ feature_gate : None ,
376
397
} ;
377
398
378
399
pub fn unused_dependencies (
@@ -383,18 +404,23 @@ pub fn unused_dependencies(
383
404
error_count : & mut usize ,
384
405
gctx : & GlobalContext ,
385
406
) -> CargoResult < ( ) > {
386
- let edition = pkg. manifest ( ) . edition ( ) ;
407
+ let manifest = pkg. manifest ( ) ;
408
+ let edition = manifest. edition ( ) ;
387
409
// Unused optional dependencies can only exist on edition 2024+
388
410
if edition < Edition :: Edition2024 {
389
411
return Ok ( ( ) ) ;
390
412
}
391
413
392
- let ( lint_level, reason) = UNUSED_OPTIONAL_DEPENDENCY . level ( pkg_lints, ws_lints, edition) ;
414
+ let ( lint_level, reason) = UNUSED_OPTIONAL_DEPENDENCY . level (
415
+ pkg_lints,
416
+ ws_lints,
417
+ edition,
418
+ manifest. unstable_features ( ) ,
419
+ ) ;
393
420
if lint_level == LintLevel :: Allow {
394
421
return Ok ( ( ) ) ;
395
422
}
396
423
let mut emitted_source = None ;
397
- let manifest = pkg. manifest ( ) ;
398
424
let original_toml = manifest. original_toml ( ) ;
399
425
// Unused dependencies were stripped from the manifest, leaving only the used ones
400
426
let used_dependencies = manifest
0 commit comments