@@ -23,6 +23,7 @@ fn parse(mut stmt: Stmt) -> Result<TokenStream> {
23
23
Stmt :: Local ( local) => Context :: default ( ) . replace_local ( local) ?,
24
24
Stmt :: Item ( Item :: Fn ( ItemFn { block, .. } ) ) => Dummy . visit_block_mut ( block) ,
25
25
Stmt :: Item ( Item :: Impl ( item) ) => replace_item_impl ( item) ,
26
+ Stmt :: Item ( Item :: Use ( item) ) => replace_item_use ( item) ?,
26
27
_ => { }
27
28
}
28
29
@@ -156,6 +157,12 @@ fn replace_item_impl(item: &mut ItemImpl) {
156
157
}
157
158
}
158
159
160
+ fn replace_item_use ( item : & mut ItemUse ) -> Result < ( ) > {
161
+ let mut visitor = UseTreeVisitor { res : Ok ( ( ) ) } ;
162
+ visitor. visit_item_use_mut ( item) ;
163
+ visitor. res
164
+ }
165
+
159
166
fn replace_ident ( ident : & mut Ident ) {
160
167
* ident = proj_ident ( ident) ;
161
168
}
@@ -197,3 +204,32 @@ impl VisitMut for Dummy {
197
204
// Do not recurse into nested items.
198
205
}
199
206
}
207
+
208
+ struct UseTreeVisitor {
209
+ res : Result < ( ) > ,
210
+ }
211
+
212
+ impl VisitMut for UseTreeVisitor {
213
+ fn visit_use_tree_mut ( & mut self , node : & mut UseTree ) {
214
+ if self . res . is_err ( ) {
215
+ return ;
216
+ }
217
+
218
+ match node {
219
+ // Desugar `use tree::<name>` into `tree::__<name>Projection`.
220
+ UseTree :: Name ( name) => replace_ident ( & mut name. ident ) ,
221
+ UseTree :: Glob ( glob) => {
222
+ self . res =
223
+ Err ( error ! ( glob, "#[project] attribute may not be used on glob imports" ) ) ;
224
+ }
225
+ UseTree :: Rename ( rename) => {
226
+ // TODO: Consider allowing the projected type to be renamed by `#[project] use Foo as Bar`.
227
+ self . res =
228
+ Err ( error ! ( rename, "#[project] attribute may not be used on renamed imports" ) ) ;
229
+ }
230
+ node @ UseTree :: Path ( _) | node @ UseTree :: Group ( _) => {
231
+ visit_mut:: visit_use_tree_mut ( self , node)
232
+ }
233
+ }
234
+ }
235
+ }
0 commit comments