@@ -53,7 +53,11 @@ extern crate clippy_utils;
53
53
use clippy_utils:: parse_msrv;
54
54
use rustc_data_structures:: fx:: FxHashSet ;
55
55
use rustc_lint:: LintId ;
56
+ use rustc_semver:: RustcVersion ;
56
57
use rustc_session:: Session ;
58
+ use std:: fs:: File ;
59
+ use std:: io:: Read ;
60
+ use toml:: Value ;
57
61
58
62
/// Macro used to declare a Clippy lint.
59
63
///
@@ -443,6 +447,50 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se
443
447
store. register_pre_expansion_pass ( move || Box :: new ( attrs:: EarlyAttributes { msrv } ) ) ;
444
448
}
445
449
450
+ fn read_msrv ( conf : & Conf , sess : & Session ) -> Option < RustcVersion > {
451
+ let clippy_msrv = conf. msrv . as_ref ( ) . and_then ( |s| {
452
+ parse_msrv ( s, None , None ) . or_else ( || {
453
+ sess. err ( & format ! (
454
+ "error reading Clippy's configuration file. `{}` is not a valid Rust version" ,
455
+ s
456
+ ) ) ;
457
+ None
458
+ } )
459
+ } ) ;
460
+
461
+ let cargo_msrv = if_chain ! {
462
+ if let Ok ( manifest_dir) = std:: env:: var( "CARGO_MANIFEST_DIR" ) ;
463
+ if let Ok ( mut file) = File :: open( format!( "{manifest_dir}/Cargo.toml" ) ) ;
464
+ let mut cargo_content_str = String :: new( ) ;
465
+ if let Ok ( _) = file. read_to_string( & mut cargo_content_str) ;
466
+ if let Ok ( cargo_content) = toml:: from_str:: <Value >( & cargo_content_str) ;
467
+ if let Some ( package) = cargo_content. get( "package" ) ;
468
+ if let Some ( rust_version) = package. get( "rust-version" ) ;
469
+ if let Some ( rust_version_str) = rust_version. as_str( ) ;
470
+ then {
471
+ parse_msrv( rust_version_str, None , None )
472
+ } else {
473
+ None
474
+ }
475
+ } ;
476
+
477
+ if let Some ( cargo_msrv) = cargo_msrv {
478
+ if let Some ( clippy_msrv) = clippy_msrv {
479
+ // if both files have an msrv, let's compare them and emit a warning if they differ
480
+ if clippy_msrv != cargo_msrv {
481
+ sess. warn ( & format ! (
482
+ "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{}`" ,
483
+ clippy_msrv
484
+ ) ) ;
485
+ return Some ( clippy_msrv) ;
486
+ }
487
+ }
488
+ Some ( cargo_msrv)
489
+ } else {
490
+ clippy_msrv
491
+ }
492
+ }
493
+
446
494
#[ doc( hidden) ]
447
495
pub fn read_conf ( sess : & Session ) -> Conf {
448
496
let file_name = match utils:: conf:: lookup_conf_file ( ) {
@@ -458,12 +506,11 @@ pub fn read_conf(sess: &Session) -> Conf {
458
506
let TryConf { conf, errors } = utils:: conf:: read ( & file_name) ;
459
507
// all conf errors are non-fatal, we just use the default conf in case of error
460
508
for error in errors {
461
- sess. struct_err ( & format ! (
509
+ sess. err ( & format ! (
462
510
"error reading Clippy's configuration file `{}`: {}" ,
463
511
file_name. display( ) ,
464
512
error
465
- ) )
466
- . emit ( ) ;
513
+ ) ) ;
467
514
}
468
515
469
516
conf
@@ -571,16 +618,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
571
618
store. register_late_pass ( || Box :: new ( non_octal_unix_permissions:: NonOctalUnixPermissions ) ) ;
572
619
store. register_early_pass ( || Box :: new ( unnecessary_self_imports:: UnnecessarySelfImports ) ) ;
573
620
574
- let msrv = conf. msrv . as_ref ( ) . and_then ( |s| {
575
- parse_msrv ( s, None , None ) . or_else ( || {
576
- sess. err ( & format ! (
577
- "error reading Clippy's configuration file. `{}` is not a valid Rust version" ,
578
- s
579
- ) ) ;
580
- None
581
- } )
582
- } ) ;
583
-
621
+ let msrv = read_msrv ( & conf, sess) ;
584
622
let avoid_breaking_exported_api = conf. avoid_breaking_exported_api ;
585
623
store. register_late_pass ( move || Box :: new ( approx_const:: ApproxConstant :: new ( msrv) ) ) ;
586
624
store. register_late_pass ( move || Box :: new ( methods:: Methods :: new ( avoid_breaking_exported_api, msrv) ) ) ;
0 commit comments