@@ -6,7 +6,8 @@ use syn::{
6
6
} ;
7
7
8
8
use crate :: utils:: {
9
- determine_lifetime_name, insert_lifetime, parse_as_empty, Mutability , SliceExt , VecExt ,
9
+ determine_lifetime_name, insert_lifetime, parse_as_empty, Immutable , Mutability , Mutable ,
10
+ Owned , SliceExt , VecExt ,
10
11
} ;
11
12
12
13
pub ( crate ) fn attribute ( args : & TokenStream , input : Stmt , mutability : Mutability ) -> TokenStream {
@@ -199,21 +200,30 @@ fn replace_item_impl(item: &mut ItemImpl, mutability: Mutability) -> Result<()>
199
200
}
200
201
201
202
fn replace_item_fn ( item : & mut ItemFn , mutability : Mutability ) -> Result < ( ) > {
202
- struct FnVisitor {
203
- res : Result < ( ) > ,
204
- mutability : Mutability ,
205
- }
203
+ struct FnVisitor ( Result < ( ) > ) ;
206
204
207
205
impl FnVisitor {
208
206
fn visit_stmt ( & mut self , node : & mut Stmt ) -> Result < ( ) > {
209
207
match node {
210
208
Stmt :: Expr ( expr) | Stmt :: Semi ( expr, _) => self . visit_expr ( expr) ,
211
209
Stmt :: Local ( local) => {
212
210
visit_mut:: visit_local_mut ( self , local) ;
213
- if let Some ( attr) = local. attrs . find_remove ( self . mutability . method_name ( ) ) ? {
214
- parse_as_empty ( & attr. tokens ) ?;
215
- Context :: new ( self . mutability ) . replace_local ( local) ?;
211
+
212
+ let mut prev = None ;
213
+ for & mutability in & [ Immutable , Mutable , Owned ] {
214
+ if let Some ( attr) = local. attrs . find_remove ( mutability. method_name ( ) ) ? {
215
+ if let Some ( prev) = prev. replace ( mutability) {
216
+ return Err ( error ! (
217
+ attr,
218
+ "attributes `{}` and `{}` are mutually exclusive" ,
219
+ prev. method_name( ) ,
220
+ mutability. method_name( ) ,
221
+ ) ) ;
222
+ }
223
+ Context :: new ( mutability) . replace_local ( local) ?;
224
+ }
216
225
}
226
+
217
227
Ok ( ( ) )
218
228
}
219
229
// Do not recurse into nested items.
@@ -223,41 +233,69 @@ fn replace_item_fn(item: &mut ItemFn, mutability: Mutability) -> Result<()> {
223
233
224
234
fn visit_expr ( & mut self , node : & mut Expr ) -> Result < ( ) > {
225
235
visit_mut:: visit_expr_mut ( self , node) ;
226
- let attr = match node {
227
- Expr :: Match ( expr) => expr. attrs . find_remove ( self . mutability . method_name ( ) ) ?,
236
+ match node {
237
+ Expr :: Match ( expr) => {
238
+ let mut prev = None ;
239
+ for & mutability in & [ Immutable , Mutable , Owned ] {
240
+ if let Some ( attr) = expr. attrs . find_remove ( mutability. method_name ( ) ) ? {
241
+ if let Some ( prev) = prev. replace ( mutability) {
242
+ return Err ( error ! (
243
+ attr,
244
+ "attributes `{}` and `{}` are mutually exclusive" ,
245
+ prev. method_name( ) ,
246
+ mutability. method_name( ) ,
247
+ ) ) ;
248
+ }
249
+ }
250
+ }
251
+ if let Some ( mutability) = prev {
252
+ replace_expr ( node, mutability) ;
253
+ }
254
+ }
228
255
Expr :: If ( expr_if) => {
229
256
if let Expr :: Let ( _) = & * expr_if. cond {
230
- expr_if. attrs . find_remove ( self . mutability . method_name ( ) ) ?
231
- } else {
232
- None
257
+ let mut prev = None ;
258
+ for & mutability in & [ Immutable , Mutable , Owned ] {
259
+ if let Some ( attr) =
260
+ expr_if. attrs . find_remove ( mutability. method_name ( ) ) ?
261
+ {
262
+ if let Some ( prev) = prev. replace ( mutability) {
263
+ return Err ( error ! (
264
+ attr,
265
+ "attributes `{}` and `{}` are mutually exclusive" ,
266
+ prev. method_name( ) ,
267
+ mutability. method_name( ) ,
268
+ ) ) ;
269
+ }
270
+ }
271
+ }
272
+ if let Some ( mutability) = prev {
273
+ replace_expr ( node, mutability) ;
274
+ }
233
275
}
234
276
}
235
- _ => return Ok ( ( ) ) ,
236
- } ;
237
- if let Some ( attr) = attr {
238
- parse_as_empty ( & attr. tokens ) ?;
239
- replace_expr ( node, self . mutability ) ;
277
+ _ => { }
240
278
}
241
279
Ok ( ( ) )
242
280
}
243
281
}
244
282
245
283
impl VisitMut for FnVisitor {
246
284
fn visit_stmt_mut ( & mut self , node : & mut Stmt ) {
247
- if self . res . is_err ( ) {
285
+ if self . 0 . is_err ( ) {
248
286
return ;
249
287
}
250
288
if let Err ( e) = self . visit_stmt ( node) {
251
- self . res = Err ( e)
289
+ self . 0 = Err ( e)
252
290
}
253
291
}
254
292
255
293
fn visit_expr_mut ( & mut self , node : & mut Expr ) {
256
- if self . res . is_err ( ) {
294
+ if self . 0 . is_err ( ) {
257
295
return ;
258
296
}
259
297
if let Err ( e) = self . visit_expr ( node) {
260
- self . res = Err ( e)
298
+ self . 0 = Err ( e)
261
299
}
262
300
}
263
301
@@ -270,9 +308,9 @@ fn replace_item_fn(item: &mut ItemFn, mutability: Mutability) -> Result<()> {
270
308
return Err ( error ! ( attr, "duplicate #[{}] attribute" , mutability. method_name( ) ) ) ;
271
309
}
272
310
273
- let mut visitor = FnVisitor { res : Ok ( ( ) ) , mutability } ;
311
+ let mut visitor = FnVisitor ( Ok ( ( ) ) ) ;
274
312
visitor. visit_block_mut ( & mut item. block ) ;
275
- visitor. res
313
+ visitor. 0
276
314
}
277
315
278
316
fn replace_item_use ( item : & mut ItemUse , mutability : Mutability ) -> Result < ( ) > {
0 commit comments