@@ -64,12 +64,22 @@ msrv_aliases! {
6464 1 , 15 , 0 { MAYBE_BOUND_IN_WHERE }
6565}
6666
67- /// Tracks the current MSRV from `clippy.toml`, `Cargo.toml` or set via `#[clippy::msrv]`
6867#[ derive( Debug , Clone ) ]
69- pub struct Msrv {
70- stack : Vec < RustcVersion > ,
68+ enum MsrvInner {
69+ One ( RustcVersion ) ,
70+ Stacked ( Vec < RustcVersion > ) ,
7171}
7272
73+ impl Default for MsrvInner {
74+ fn default ( ) -> Self {
75+ Self :: Stacked ( Vec :: new ( ) )
76+ }
77+ }
78+
79+ /// Tracks the current MSRV from `clippy.toml`, `Cargo.toml` or set via `#[clippy::msrv]`
80+ #[ derive( Debug , Clone ) ]
81+ pub struct Msrv ( MsrvInner ) ;
82+
7383impl fmt:: Display for Msrv {
7484 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
7585 if let Some ( msrv) = self . current ( ) {
@@ -87,14 +97,14 @@ impl<'de> Deserialize<'de> for Msrv {
8797 {
8898 let v = String :: deserialize ( deserializer) ?;
8999 parse_version ( Symbol :: intern ( & v) )
90- . map ( |v| Msrv { stack : vec ! [ v ] } )
100+ . map ( |v| Msrv ( MsrvInner :: One ( v ) ) )
91101 . ok_or_else ( || serde:: de:: Error :: custom ( "not a valid Rust version" ) )
92102 }
93103}
94104
95105impl Msrv {
96106 pub fn empty ( ) -> Msrv {
97- Msrv { stack : Vec :: new ( ) }
107+ Msrv ( MsrvInner :: Stacked ( Vec :: new ( ) ) )
98108 }
99109
100110 pub fn read_cargo ( & mut self , sess : & Session ) {
@@ -103,7 +113,7 @@ impl Msrv {
103113 . and_then ( |v| parse_version ( Symbol :: intern ( & v) ) ) ;
104114
105115 match ( self . current ( ) , cargo_msrv) {
106- ( None , Some ( cargo_msrv) ) => self . stack = vec ! [ cargo_msrv] ,
116+ ( None , Some ( cargo_msrv) ) => self . 0 = MsrvInner :: One ( cargo_msrv) ,
107117 ( Some ( clippy_msrv) , Some ( cargo_msrv) ) => {
108118 if clippy_msrv != cargo_msrv {
109119 sess. dcx ( ) . warn ( format ! (
@@ -116,7 +126,10 @@ impl Msrv {
116126 }
117127
118128 pub fn current ( & self ) -> Option < RustcVersion > {
119- self . stack . last ( ) . copied ( )
129+ match & self . 0 {
130+ MsrvInner :: One ( ver) => Some ( * ver) ,
131+ MsrvInner :: Stacked ( vec) => vec. last ( ) . copied ( ) ,
132+ }
120133 }
121134
122135 pub fn meets ( & self , required : RustcVersion ) -> bool {
@@ -152,13 +165,26 @@ impl Msrv {
152165
153166 pub fn check_attributes ( & mut self , sess : & Session , attrs : & [ Attribute ] ) {
154167 if let Some ( version) = Self :: parse_attr ( sess, attrs) {
155- self . stack . push ( version) ;
168+ self . 0 = match std:: mem:: take ( & mut self . 0 ) {
169+ MsrvInner :: Stacked ( stack) if stack. is_empty ( ) && stack. capacity ( ) == 0 => MsrvInner :: One ( version) ,
170+ MsrvInner :: One ( old) => MsrvInner :: Stacked ( vec ! [ old, version] ) ,
171+ MsrvInner :: Stacked ( mut stack) => {
172+ stack. push ( version) ;
173+ MsrvInner :: Stacked ( stack)
174+ } ,
175+ } ;
156176 }
157177 }
158178
159179 pub fn check_attributes_post ( & mut self , sess : & Session , attrs : & [ Attribute ] ) {
160180 if Self :: parse_attr ( sess, attrs) . is_some ( ) {
161- self . stack . pop ( ) ;
181+ self . 0 = match std:: mem:: take ( & mut self . 0 ) {
182+ MsrvInner :: One ( _) => MsrvInner :: Stacked ( Vec :: new ( ) ) ,
183+ MsrvInner :: Stacked ( mut vec) => {
184+ vec. pop ( ) ;
185+ MsrvInner :: Stacked ( vec)
186+ } ,
187+ }
162188 }
163189 }
164190}
0 commit comments