@@ -13,12 +13,12 @@ pub(crate) fn attribute(args: &TokenStream, input: Stmt, mutability: Mutability)
13
13
. unwrap_or_else ( |e| e. to_compile_error ( ) )
14
14
}
15
15
16
- fn replace_stmt ( stmt : & mut Stmt , mutability : Mutability ) -> Result < ( ) > {
17
- match stmt {
18
- Stmt :: Expr ( Expr :: Match ( expr) ) | Stmt :: Semi ( Expr :: Match ( expr ) , _ ) => {
16
+ fn replace_expr ( expr : & mut Expr , mutability : Mutability ) {
17
+ match expr {
18
+ Expr :: Match ( expr) => {
19
19
Context :: new ( mutability) . replace_expr_match ( expr) ;
20
20
}
21
- Stmt :: Expr ( Expr :: If ( expr_if) ) => {
21
+ Expr :: If ( expr_if) => {
22
22
let mut expr_if = expr_if;
23
23
while let Expr :: Let ( ref mut expr) = & mut * expr_if. cond {
24
24
Context :: new ( mutability) . replace_expr_let ( expr) ;
@@ -31,15 +31,14 @@ fn replace_stmt(stmt: &mut Stmt, mutability: Mutability) -> Result<()> {
31
31
break ;
32
32
}
33
33
}
34
- Stmt :: Local ( local) => Context :: new ( mutability) . replace_local ( local) ?,
35
34
_ => { }
36
35
}
37
- Ok ( ( ) )
38
36
}
39
37
40
38
fn parse ( mut stmt : Stmt , mutability : Mutability ) -> Result < TokenStream > {
41
- replace_stmt ( & mut stmt, mutability) ?;
42
39
match & mut stmt {
40
+ Stmt :: Expr ( expr) | Stmt :: Semi ( expr, _) => replace_expr ( expr, mutability) ,
41
+ Stmt :: Local ( local) => Context :: new ( mutability) . replace_local ( local) ?,
43
42
Stmt :: Item ( Item :: Fn ( item) ) => replace_item_fn ( item, mutability) ?,
44
43
Stmt :: Item ( Item :: Impl ( item) ) => replace_item_impl ( item, mutability) ,
45
44
Stmt :: Item ( Item :: Use ( item) ) => replace_item_use ( item, mutability) ?,
@@ -68,7 +67,7 @@ impl Context {
68
67
69
68
fn compare_paths ( & self , ident : & Ident , len : usize ) -> bool {
70
69
match & self . register {
71
- Some ( ( i, l) ) => * l == len && ident == i ,
70
+ Some ( ( i, l) ) => * l == len && i == ident ,
72
71
None => false ,
73
72
}
74
73
}
@@ -99,7 +98,7 @@ impl Context {
99
98
}
100
99
101
100
fn replace_expr_match ( & mut self , expr : & mut ExprMatch ) {
102
- expr. arms . iter_mut ( ) . for_each ( |Arm { pat , .. } | self . replace_pat ( pat, true ) )
101
+ expr. arms . iter_mut ( ) . for_each ( |arm | self . replace_pat ( & mut arm . pat , true ) )
103
102
}
104
103
105
104
fn replace_pat ( & mut self , pat : & mut Pat , allow_pat_path : bool ) {
@@ -155,6 +154,10 @@ fn is_replaceable(pat: &Pat, allow_pat_path: bool) -> bool {
155
154
}
156
155
}
157
156
157
+ fn replace_ident ( ident : & mut Ident , mutability : Mutability ) {
158
+ * ident = proj_ident ( ident, mutability) ;
159
+ }
160
+
158
161
fn replace_item_impl ( item : & mut ItemImpl , mutability : Mutability ) {
159
162
let PathSegment { ident, arguments } = match & mut * item. self_ty {
160
163
Type :: Path ( TypePath { qself : None , path } ) => path. segments . last_mut ( ) . unwrap ( ) ,
@@ -185,106 +188,122 @@ fn replace_item_impl(item: &mut ItemImpl, mutability: Mutability) {
185
188
}
186
189
187
190
fn replace_item_fn ( item : & mut ItemFn , mutability : Mutability ) -> Result < ( ) > {
188
- let mut visitor = FnVisitor { res : Ok ( ( ) ) , mutability } ;
189
- visitor. visit_block_mut ( & mut item. block ) ;
190
- visitor. res
191
- }
192
-
193
- fn replace_item_use ( item : & mut ItemUse , mutability : Mutability ) -> Result < ( ) > {
194
- let mut visitor = UseTreeVisitor { res : Ok ( ( ) ) , mutability } ;
195
- visitor. visit_item_use_mut ( item) ;
196
- visitor. res
197
- }
198
-
199
- fn replace_ident ( ident : & mut Ident , mutability : Mutability ) {
200
- * ident = proj_ident ( ident, mutability) ;
201
- }
202
-
203
- // =================================================================================================
204
- // visitors
205
-
206
- struct FnVisitor {
207
- res : Result < ( ) > ,
208
- mutability : Mutability ,
209
- }
191
+ struct FnVisitor {
192
+ res : Result < ( ) > ,
193
+ mutability : Mutability ,
194
+ }
210
195
211
- impl FnVisitor {
212
- /// Returns the attribute name.
213
- fn name ( & self ) -> & str {
214
- match self . mutability {
215
- Mutable => "project" ,
216
- Immutable => "project_ref" ,
217
- Owned => "project_replace" ,
196
+ impl FnVisitor {
197
+ /// Returns the attribute name.
198
+ fn name ( & self ) -> & str {
199
+ match self . mutability {
200
+ Mutable => "project" ,
201
+ Immutable => "project_ref" ,
202
+ Owned => "project_replace" ,
203
+ }
218
204
}
219
- }
220
205
221
- fn visit_stmt ( & mut self , node : & mut Stmt ) -> Result < ( ) > {
222
- let attr = match node {
223
- Stmt :: Expr ( Expr :: Match ( expr) ) | Stmt :: Semi ( Expr :: Match ( expr) , _) => {
224
- expr. attrs . find_remove ( self . name ( ) ) ?
206
+ fn visit_stmt ( & mut self , node : & mut Stmt ) -> Result < ( ) > {
207
+ match node {
208
+ Stmt :: Expr ( expr) | Stmt :: Semi ( expr, _) => {
209
+ visit_mut:: visit_expr_mut ( self , expr) ;
210
+ self . visit_expr ( expr)
211
+ }
212
+ Stmt :: Local ( local) => {
213
+ visit_mut:: visit_local_mut ( self , local) ;
214
+ if let Some ( attr) = local. attrs . find_remove ( self . name ( ) ) ? {
215
+ parse_as_empty ( & attr. tokens ) ?;
216
+ Context :: new ( self . mutability ) . replace_local ( local) ?;
217
+ }
218
+ Ok ( ( ) )
219
+ }
220
+ // Do not recurse into nested items.
221
+ Stmt :: Item ( _) => Ok ( ( ) ) ,
225
222
}
226
- Stmt :: Local ( local) => local. attrs . find_remove ( self . name ( ) ) ?,
227
- Stmt :: Expr ( Expr :: If ( expr_if) ) => {
228
- if let Expr :: Let ( _) = & * expr_if. cond {
229
- expr_if. attrs . find_remove ( self . name ( ) ) ?
230
- } else {
231
- None
223
+ }
224
+
225
+ fn visit_expr ( & mut self , node : & mut Expr ) -> Result < ( ) > {
226
+ let attr = match node {
227
+ Expr :: Match ( expr) => expr. attrs . find_remove ( self . name ( ) ) ?,
228
+ Expr :: If ( expr_if) => {
229
+ if let Expr :: Let ( _) = & * expr_if. cond {
230
+ expr_if. attrs . find_remove ( self . name ( ) ) ?
231
+ } else {
232
+ None
233
+ }
232
234
}
235
+ _ => return Ok ( ( ) ) ,
236
+ } ;
237
+ if let Some ( attr) = attr {
238
+ parse_as_empty ( & attr. tokens ) ?;
239
+ replace_expr ( node, self . mutability ) ;
233
240
}
234
- _ => return Ok ( ( ) ) ,
235
- } ;
236
- if let Some ( attr) = attr {
237
- parse_as_empty ( & attr. tokens ) ?;
238
- replace_stmt ( node, self . mutability ) ?;
241
+ Ok ( ( ) )
239
242
}
240
- Ok ( ( ) )
241
243
}
242
- }
243
244
244
- impl VisitMut for FnVisitor {
245
- fn visit_stmt_mut ( & mut self , node : & mut Stmt ) {
246
- if self . res . is_err ( ) {
247
- return ;
245
+ impl VisitMut for FnVisitor {
246
+ fn visit_stmt_mut ( & mut self , node : & mut Stmt ) {
247
+ if self . res . is_err ( ) {
248
+ return ;
249
+ }
250
+ if let Err ( e) = self . visit_stmt ( node) {
251
+ self . res = Err ( e)
252
+ }
248
253
}
249
254
250
- visit_mut:: visit_stmt_mut ( self , node) ;
251
-
252
- if let Err ( e) = self . visit_stmt ( node) {
253
- self . res = Err ( e)
255
+ fn visit_expr_mut ( & mut self , node : & mut Expr ) {
256
+ if self . res . is_err ( ) {
257
+ return ;
258
+ }
259
+ if let Err ( e) = self . visit_expr ( node) {
260
+ self . res = Err ( e)
261
+ }
254
262
}
255
- }
256
263
257
- fn visit_item_mut ( & mut self , _: & mut Item ) {
258
- // Do not recurse into nested items.
264
+ fn visit_item_mut ( & mut self , _: & mut Item ) {
265
+ // Do not recurse into nested items.
266
+ }
259
267
}
260
- }
261
268
262
- struct UseTreeVisitor {
263
- res : Result < ( ) > ,
264
- mutability : Mutability ,
269
+ let mut visitor = FnVisitor { res : Ok ( ( ) ) , mutability } ;
270
+ visitor . visit_block_mut ( & mut item . block ) ;
271
+ visitor . res
265
272
}
266
273
267
- impl VisitMut for UseTreeVisitor {
268
- fn visit_use_tree_mut ( & mut self , node : & mut UseTree ) {
269
- if self . res . is_err ( ) {
270
- return ;
271
- }
274
+ fn replace_item_use ( item : & mut ItemUse , mutability : Mutability ) -> Result < ( ) > {
275
+ struct UseTreeVisitor {
276
+ res : Result < ( ) > ,
277
+ mutability : Mutability ,
278
+ }
272
279
273
- match node {
274
- // Desugar `use tree::<name>` into `tree::__<name>Projection`.
275
- UseTree :: Name ( name) => replace_ident ( & mut name. ident , self . mutability ) ,
276
- UseTree :: Glob ( glob) => {
277
- self . res =
278
- Err ( error ! ( glob, "#[project] attribute may not be used on glob imports" ) ) ;
280
+ impl VisitMut for UseTreeVisitor {
281
+ fn visit_use_tree_mut ( & mut self , node : & mut UseTree ) {
282
+ if self . res . is_err ( ) {
283
+ return ;
279
284
}
280
- UseTree :: Rename ( rename) => {
281
- // TODO: Consider allowing the projected type to be renamed by `#[project] use Foo as Bar`.
282
- self . res =
283
- Err ( error ! ( rename, "#[project] attribute may not be used on renamed imports" ) ) ;
284
- }
285
- node @ UseTree :: Path ( _) | node @ UseTree :: Group ( _) => {
286
- visit_mut:: visit_use_tree_mut ( self , node)
285
+
286
+ match node {
287
+ // Desugar `use tree::<name>` into `tree::__<name>Projection`.
288
+ UseTree :: Name ( name) => replace_ident ( & mut name. ident , self . mutability ) ,
289
+ UseTree :: Glob ( glob) => {
290
+ self . res =
291
+ Err ( error ! ( glob, "#[project] attribute may not be used on glob imports" ) ) ;
292
+ }
293
+ UseTree :: Rename ( rename) => {
294
+ self . res = Err ( error ! (
295
+ rename,
296
+ "#[project] attribute may not be used on renamed imports"
297
+ ) ) ;
298
+ }
299
+ node @ UseTree :: Path ( _) | node @ UseTree :: Group ( _) => {
300
+ visit_mut:: visit_use_tree_mut ( self , node)
301
+ }
287
302
}
288
303
}
289
304
}
305
+
306
+ let mut visitor = UseTreeVisitor { res : Ok ( ( ) ) , mutability } ;
307
+ visitor. visit_item_use_mut ( item) ;
308
+ visitor. res
290
309
}
0 commit comments