11use std:: borrow:: Cow ;
22use std:: fmt:: Display ;
33
4+ use rustc_ast:: attr:: version:: RustcVersion ;
45use rustc_data_structures:: fx:: FxIndexSet ;
56use rustc_data_structures:: stable_hash:: { StableCompare , StableHash , StableHashCtxt , StableHasher } ;
67use rustc_error_messages:: { DiagArgValue , IntoDiagArg } ;
@@ -305,6 +306,9 @@ pub struct Lint {
305306
306307 /// `true` if this lint is unaffected by `-D warnings`
307308 pub ignore_deny_warnings : bool ,
309+
310+ /// Used to avoid lints which would affect MSRV
311+ pub rust_version : Option < RustcVersion > ,
308312}
309313
310314/// Extra information for a future incompatibility lint.
@@ -521,7 +525,40 @@ impl Lint {
521525 crate_level_only : false ,
522526 eval_always : false ,
523527 ignore_deny_warnings : false ,
528+ rust_version : None ,
529+ }
530+ }
531+
532+ // FIXME(const-hack): This is used so that `declare_lint` can declare an MSRV statically.
533+ // `RustcVersion::parse_str_strict` should ideally be used instead.
534+ pub const fn parse_rust_version ( version : & str ) -> RustcVersion {
535+ const fn parse_part ( input : & mut & [ u8 ] ) -> u16 {
536+ let mut val = 0 ;
537+ let mut idx = 0 ;
538+ while idx < input. len ( ) {
539+ let v = input[ idx] ;
540+ match v {
541+ b'0' ..=b'9' => {
542+ val = val * 10 + ( v - b'0' ) as u16 ;
543+ }
544+ b'.' => {
545+ idx += 1 ;
546+ break ;
547+ }
548+ _ => panic ! ( "invalid character in version" ) ,
549+ }
550+ idx += 1 ;
551+ }
552+ * input = input. split_at ( idx) . 1 ;
553+ val
524554 }
555+
556+ let mut bytes = version. as_bytes ( ) ;
557+ let major = parse_part ( & mut bytes) ;
558+ let minor = parse_part ( & mut bytes) ;
559+ let patch = parse_part ( & mut bytes) ;
560+ assert ! ( bytes. is_empty( ) ) ;
561+ RustcVersion { major, minor, patch }
525562 }
526563
527564 /// Gets the lint's name, with ASCII letters converted to lowercase.
@@ -671,6 +708,7 @@ macro_rules! declare_lint {
671708 $( $field: ident : $val: expr) ,* $( , ) *
672709 } ; ) ?
673710 $( @edition $lint_edition: ident => $edition_level: ident; ) ?
711+ $( @msrv = $msrv: literal; ) ?
674712 $( $v: ident) ,* ) => (
675713 $( #[ $attr] ) *
676714 $vis static $NAME: & $crate:: Lint = & $crate:: Lint {
@@ -687,6 +725,7 @@ macro_rules! declare_lint {
687725 } ) , ) ?
688726 $( edition_lint_opts: Some ( ( $crate:: Edition :: $lint_edition, $crate:: $edition_level) ) , ) ?
689727 $( eval_always: $eval_always, ) ?
728+ $( rust_version: Some ( $crate:: Lint :: parse_rust_version( $msrv) ) , ) ?
690729 ..$crate:: Lint :: default_fields_for_macro( )
691730 } ;
692731 ) ;
0 commit comments