@@ -182,13 +182,11 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
182
182
item : & ' c ast:: Item ,
183
183
sub_mod : Module < ' _ > ,
184
184
) -> Result < ( ) , ModuleResolutionError > {
185
- let old_directory = self . directory . clone ( ) ;
186
185
let sub_mod_kind = self . peek_sub_mod ( item, & sub_mod) ?;
187
186
if let Some ( sub_mod_kind) = sub_mod_kind {
188
187
self . insert_sub_mod ( sub_mod_kind. clone ( ) ) ?;
189
188
self . visit_sub_mod_inner ( sub_mod, sub_mod_kind) ?;
190
189
}
191
- self . directory = old_directory;
192
190
Ok ( ( ) )
193
191
}
194
192
@@ -245,34 +243,23 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
245
243
path : mod_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ,
246
244
ownership : directory_ownership,
247
245
} ;
248
- self . visit_sub_mod_after_directory_update ( sub_mod , Some ( directory ) )
246
+ self . with_directory ( directory , |this| this . visit_mod ( & sub_mod . items ) ) ? ;
249
247
}
250
248
SubModKind :: Internal ( item) => {
251
- self . push_inline_mod_directory ( item. ident , & item. attrs ) ;
252
- self . visit_sub_mod_after_directory_update ( sub_mod , None )
249
+ let directory = self . inline_mod_directory ( item. ident , & item. attrs ) ;
250
+ self . with_directory ( directory , |this| this . visit_mod ( & sub_mod . items ) ) ? ;
253
251
}
254
252
SubModKind :: MultiExternal ( mods) => {
255
253
for ( mod_path, directory_ownership, sub_mod) in mods {
256
254
let directory = Directory {
257
255
path : mod_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ,
258
256
ownership : directory_ownership,
259
257
} ;
260
- self . visit_sub_mod_after_directory_update ( sub_mod , Some ( directory ) ) ?;
258
+ self . with_directory ( directory , |this| this . visit_mod ( & sub_mod . items ) ) ?;
261
259
}
262
- Ok ( ( ) )
263
260
}
264
261
}
265
- }
266
-
267
- fn visit_sub_mod_after_directory_update (
268
- & mut self ,
269
- sub_mod : Module < ' _ > ,
270
- directory : Option < Directory > ,
271
- ) -> Result < ( ) , ModuleResolutionError > {
272
- if let Some ( directory) = directory {
273
- self . directory = directory;
274
- }
275
- self . visit_mod ( & sub_mod. items )
262
+ Ok ( ( ) )
276
263
}
277
264
278
265
/// Find a file path in the filesystem which corresponds to the given module.
@@ -404,31 +391,41 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
404
391
}
405
392
}
406
393
407
- fn push_inline_mod_directory ( & mut self , id : symbol:: Ident , attrs : & [ ast:: Attribute ] ) {
394
+ fn inline_mod_directory ( & mut self , id : symbol:: Ident , attrs : & [ ast:: Attribute ] ) -> Directory {
408
395
if let Some ( path) = find_path_value ( attrs) {
409
- self . directory . path . push ( path. as_str ( ) ) ;
410
- self . directory . ownership = DirectoryOwnership :: Owned { relative : None } ;
411
- } else {
412
- let id = id. as_str ( ) ;
413
- // We have to push on the current module name in the case of relative
414
- // paths in order to ensure that any additional module paths from inline
415
- // `mod x { ... }` come after the relative extension.
416
- //
417
- // For example, a `mod z { ... }` inside `x/y.rs` should set the current
418
- // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
419
- if let DirectoryOwnership :: Owned { relative } = & mut self . directory . ownership {
420
- if let Some ( ident) = relative. take ( ) {
421
- // remove the relative offset
422
- self . directory . path . push ( ident. as_str ( ) ) ;
423
-
424
- // In the case where there is an x.rs and an ./x directory we want
425
- // to prevent adding x twice. For example, ./x/x
426
- if self . directory . path . exists ( ) && !self . directory . path . join ( id) . exists ( ) {
427
- return ;
428
- }
429
- }
396
+ return Directory {
397
+ path : self . directory . path . join ( path. as_str ( ) ) ,
398
+ ownership : DirectoryOwnership :: Owned { relative : None } ,
399
+ } ;
400
+ }
401
+ let id = id. as_str ( ) ;
402
+ // We have to push on the current module name in the case of relative
403
+ // paths in order to ensure that any additional module paths from inline
404
+ // `mod x { ... }` come after the relative extension.
405
+ //
406
+ // For example, a `mod z { ... }` inside `x/y.rs` should set the current
407
+ // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
408
+ let new_path = if let DirectoryOwnership :: Owned {
409
+ relative : Some ( ident) ,
410
+ } = self . directory . ownership
411
+ {
412
+ // remove the relative offset
413
+ let relative = self . directory . path . join ( ident. as_str ( ) ) ;
414
+ let nested = relative. join ( id) ;
415
+
416
+ // In the case where there is an x.rs and an ./x directory we want
417
+ // to prevent adding x twice. For example, ./x/x
418
+ if relative. exists ( ) && !nested. exists ( ) {
419
+ relative
420
+ } else {
421
+ nested
430
422
}
431
- self . directory . path . push ( id) ;
423
+ } else {
424
+ self . directory . path . join ( id)
425
+ } ;
426
+ Directory {
427
+ path : new_path,
428
+ ownership : self . directory . ownership ,
432
429
}
433
430
}
434
431
@@ -446,8 +443,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
446
443
}
447
444
let mut result = vec ! [ ] ;
448
445
for path in path_visitor. paths ( ) {
449
- let mut actual_path = self . directory . path . clone ( ) ;
450
- actual_path. push ( & path) ;
446
+ let actual_path = self . directory . path . join ( path) ;
451
447
if !actual_path. exists ( ) {
452
448
continue ;
453
449
}
@@ -475,6 +471,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
475
471
}
476
472
result
477
473
}
474
+
475
+ fn with_directory < T > ( & mut self , directory : Directory , f : impl FnOnce ( & mut Self ) -> T ) -> T {
476
+ let old = std:: mem:: replace ( & mut self . directory , directory) ;
477
+ let out = f ( self ) ;
478
+ self . directory = old;
479
+ out
480
+ }
478
481
}
479
482
480
483
fn path_value ( attr : & ast:: Attribute ) -> Option < Symbol > {
0 commit comments