@@ -50,11 +50,14 @@ extern crate rustc_typeck;
50
50
#[ macro_use]
51
51
extern crate clippy_utils;
52
52
53
- use cargo_metadata:: MetadataCommand ;
54
53
use clippy_utils:: parse_msrv;
55
54
use rustc_data_structures:: fx:: FxHashSet ;
56
55
use rustc_lint:: LintId ;
56
+ use rustc_semver:: RustcVersion ;
57
57
use rustc_session:: Session ;
58
+ use std:: fs:: File ;
59
+ use std:: io:: Read ;
60
+ use toml:: Value ;
58
61
59
62
/// Macro used to declare a Clippy lint.
60
63
///
@@ -444,6 +447,24 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se
444
447
store. register_pre_expansion_pass ( move || Box :: new ( attrs:: EarlyAttributes { msrv } ) ) ;
445
448
}
446
449
450
+ fn cargo_toml_msrv ( ) -> Option < RustcVersion > {
451
+ if_chain ! {
452
+ if let Ok ( manifest_dir) = std:: env:: var( "CARGO_MANIFEST_DIR" ) ;
453
+ if let Ok ( mut file) = File :: open( format!( "{manifest_dir}/Cargo.toml" ) ) ;
454
+ let mut cargo_content_str = String :: new( ) ;
455
+ if let Ok ( _) = file. read_to_string( & mut cargo_content_str) ;
456
+ if let Ok ( cargo_content) = toml:: from_str:: <Value >( & cargo_content_str) ;
457
+ if let Some ( package) = cargo_content. get( "package" ) ;
458
+ if let Some ( rust_version) = package. get( "rust-version" ) ;
459
+ if let Some ( rust_version_str) = rust_version. as_str( ) ;
460
+ then {
461
+ parse_msrv( rust_version_str, None , None )
462
+ } else {
463
+ None
464
+ }
465
+ }
466
+ }
467
+
447
468
#[ doc( hidden) ]
448
469
pub fn read_conf ( sess : & Session ) -> Conf {
449
470
let file_name = match utils:: conf:: lookup_conf_file ( ) {
@@ -459,23 +480,34 @@ pub fn read_conf(sess: &Session) -> Conf {
459
480
let TryConf { mut conf, errors } = utils:: conf:: read ( & file_name) ;
460
481
// all conf errors are non-fatal, we just use the default conf in case of error
461
482
for error in errors {
462
- sess. struct_err ( & format ! (
483
+ sess. err ( & format ! (
463
484
"error reading Clippy's configuration file `{}`: {}" ,
464
485
file_name. display( ) ,
465
486
error
466
- ) )
467
- . emit ( ) ;
487
+ ) ) ;
468
488
}
469
489
470
- if conf. msrv . is_none ( ) {
471
- // let's try to get msrv from `Cargo.toml`s field `rust-version`
472
- if let Ok ( metadata) = MetadataCommand :: new ( ) . no_deps ( ) . exec ( ) {
473
- conf. msrv = metadata
474
- . packages
475
- . get ( 0 )
476
- . and_then ( |x| x. rust_version . as_ref ( ) )
477
- . and_then ( |r| r. comparators . get ( 0 ) )
478
- . map ( |v| format ! ( "{}.{}.{}" , v. major, v. minor. unwrap_or( 0 ) , v. patch. unwrap_or( 0 ) ) ) ;
490
+ let clippy_msrv = conf. msrv . as_ref ( ) . and_then ( |s| {
491
+ parse_msrv ( s, None , None ) . or_else ( || {
492
+ sess. err ( & format ! (
493
+ "error reading Clippy's configuration file. `{}` is not a valid Rust version" ,
494
+ s
495
+ ) ) ;
496
+ None
497
+ } )
498
+ } ) ;
499
+ if let Some ( cargo_msrv) = cargo_toml_msrv ( ) {
500
+ if let Some ( clippy_msrv) = clippy_msrv {
501
+ // if both files have an msrv, let's compare them and emit a warning if they differ
502
+ if clippy_msrv != cargo_msrv {
503
+ sess. warn ( & format ! (
504
+ "The MSRV in `clippy.toml` and `Cargo.toml` differ. Using `{}`" ,
505
+ clippy_msrv
506
+ ) ) ;
507
+ }
508
+ } else {
509
+ // assign msrv from cargo.toml if clippy.toml hasn't set one alreay
510
+ conf. msrv = Some ( cargo_msrv. to_string ( ) ) ;
479
511
}
480
512
}
481
513
@@ -584,16 +616,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
584
616
store. register_late_pass ( || Box :: new ( non_octal_unix_permissions:: NonOctalUnixPermissions ) ) ;
585
617
store. register_early_pass ( || Box :: new ( unnecessary_self_imports:: UnnecessarySelfImports ) ) ;
586
618
587
- let msrv = conf. msrv . as_ref ( ) . and_then ( |s| {
588
- parse_msrv ( s, None , None ) . or_else ( || {
589
- sess. err ( & format ! (
590
- "error reading Clippy's configuration file. `{}` is not a valid Rust version" ,
591
- s
592
- ) ) ;
593
- None
594
- } )
595
- } ) ;
596
-
619
+ let msrv = conf. msrv . as_ref ( ) . and_then ( |s| parse_msrv ( s, None , None ) ) ;
597
620
let avoid_breaking_exported_api = conf. avoid_breaking_exported_api ;
598
621
store. register_late_pass ( move || Box :: new ( approx_const:: ApproxConstant :: new ( msrv) ) ) ;
599
622
store. register_late_pass ( move || Box :: new ( methods:: Methods :: new ( avoid_breaking_exported_api, msrv) ) ) ;
0 commit comments