@@ -220,13 +220,11 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
220
220
sub_mod : Module < ' _ > ,
221
221
from_ast : bool ,
222
222
) -> Result < ( ) , ModuleResolutionError > {
223
- let old_directory = self . directory . clone ( ) ;
224
223
let sub_mod_kind = self . peek_sub_mod ( item, & sub_mod) ?;
225
224
if let Some ( sub_mod_kind) = sub_mod_kind {
226
225
self . insert_sub_mod ( sub_mod_kind. clone ( ) ) ?;
227
226
self . visit_sub_mod_inner ( sub_mod, sub_mod_kind, from_ast) ?;
228
227
}
229
- self . directory = old_directory;
230
228
Ok ( ( ) )
231
229
}
232
230
@@ -284,39 +282,30 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
284
282
path : mod_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ,
285
283
ownership : directory_ownership,
286
284
} ;
287
- self . visit_sub_mod_after_directory_update ( sub_mod , Some ( directory ) , false )
285
+ self . with_directory ( directory , |this| this . visit_mod_outside_ast ( & sub_mod . items ) ) ? ;
288
286
}
289
287
SubModKind :: Internal ( item) => {
290
- self . push_inline_mod_directory ( item. ident , & item. attrs ) ;
291
- self . visit_sub_mod_after_directory_update ( sub_mod, None , from_ast)
288
+ let directory = self . inline_mod_directory ( item. ident , & item. attrs ) ;
289
+ self . with_directory ( directory, |this| {
290
+ if from_ast {
291
+ this. visit_mod_from_ast ( & sub_mod. items )
292
+ } else {
293
+ this. visit_mod_outside_ast ( & sub_mod. items )
294
+ }
295
+ } ) ?;
292
296
}
293
297
SubModKind :: MultiExternal ( mods) => {
294
298
for ( mod_path, directory_ownership, sub_mod) in mods {
295
299
let directory = Directory {
296
300
path : mod_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ,
297
301
ownership : directory_ownership,
298
302
} ;
299
- self . visit_sub_mod_after_directory_update ( sub_mod, Some ( directory) , false ) ?;
303
+ self . with_directory ( directory, |this| {
304
+ this. visit_mod_outside_ast ( & sub_mod. items )
305
+ } ) ?;
300
306
}
301
- Ok ( ( ) )
302
307
}
303
308
}
304
- }
305
-
306
- fn visit_sub_mod_after_directory_update (
307
- & mut self ,
308
- sub_mod : Module < ' _ > ,
309
- directory : Option < Directory > ,
310
- from_ast : bool ,
311
- ) -> Result < ( ) , ModuleResolutionError > {
312
- if let Some ( directory) = directory {
313
- self . directory = directory;
314
- }
315
- if from_ast {
316
- self . visit_mod_from_ast ( & sub_mod. items ) ?;
317
- } else {
318
- self . visit_mod_outside_ast ( & sub_mod. items ) ?;
319
- }
320
309
Ok ( ( ) )
321
310
}
322
311
@@ -449,31 +438,41 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
449
438
}
450
439
}
451
440
452
- fn push_inline_mod_directory ( & mut self , id : symbol:: Ident , attrs : & [ ast:: Attribute ] ) {
441
+ fn inline_mod_directory ( & mut self , id : symbol:: Ident , attrs : & [ ast:: Attribute ] ) -> Directory {
453
442
if let Some ( path) = find_path_value ( attrs) {
454
- self . directory . path . push ( path. as_str ( ) ) ;
455
- self . directory . ownership = DirectoryOwnership :: Owned { relative : None } ;
456
- } else {
457
- let id = id. as_str ( ) ;
458
- // We have to push on the current module name in the case of relative
459
- // paths in order to ensure that any additional module paths from inline
460
- // `mod x { ... }` come after the relative extension.
461
- //
462
- // For example, a `mod z { ... }` inside `x/y.rs` should set the current
463
- // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
464
- if let DirectoryOwnership :: Owned { relative } = & mut self . directory . ownership {
465
- if let Some ( ident) = relative. take ( ) {
466
- // remove the relative offset
467
- self . directory . path . push ( ident. as_str ( ) ) ;
468
-
469
- // In the case where there is an x.rs and an ./x directory we want
470
- // to prevent adding x twice. For example, ./x/x
471
- if self . directory . path . exists ( ) && !self . directory . path . join ( id) . exists ( ) {
472
- return ;
473
- }
474
- }
443
+ return Directory {
444
+ path : self . directory . path . join ( path. as_str ( ) ) ,
445
+ ownership : DirectoryOwnership :: Owned { relative : None } ,
446
+ } ;
447
+ }
448
+ let id = id. as_str ( ) ;
449
+ // We have to push on the current module name in the case of relative
450
+ // paths in order to ensure that any additional module paths from inline
451
+ // `mod x { ... }` come after the relative extension.
452
+ //
453
+ // For example, a `mod z { ... }` inside `x/y.rs` should set the current
454
+ // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
455
+ let new_path = if let DirectoryOwnership :: Owned {
456
+ relative : Some ( ident) ,
457
+ } = self . directory . ownership
458
+ {
459
+ // remove the relative offset
460
+ let relative = self . directory . path . join ( ident. as_str ( ) ) ;
461
+ let nested = relative. join ( id) ;
462
+
463
+ // In the case where there is an x.rs and an ./x directory we want
464
+ // to prevent adding x twice. For example, ./x/x
465
+ if relative. exists ( ) && !nested. exists ( ) {
466
+ relative
467
+ } else {
468
+ nested
475
469
}
476
- self . directory . path . push ( id) ;
470
+ } else {
471
+ self . directory . path . join ( id)
472
+ } ;
473
+ Directory {
474
+ path : new_path,
475
+ ownership : self . directory . ownership ,
477
476
}
478
477
}
479
478
@@ -491,8 +490,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
491
490
}
492
491
let mut result = vec ! [ ] ;
493
492
for path in path_visitor. paths ( ) {
494
- let mut actual_path = self . directory . path . clone ( ) ;
495
- actual_path. push ( & path) ;
493
+ let actual_path = self . directory . path . join ( path) ;
496
494
if !actual_path. exists ( ) {
497
495
continue ;
498
496
}
@@ -520,6 +518,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
520
518
}
521
519
result
522
520
}
521
+
522
+ fn with_directory < T > ( & mut self , directory : Directory , f : impl FnOnce ( & mut Self ) -> T ) -> T {
523
+ let old = std:: mem:: replace ( & mut self . directory , directory) ;
524
+ let out = f ( self ) ;
525
+ self . directory = old;
526
+ out
527
+ }
523
528
}
524
529
525
530
fn path_value ( attr : & ast:: Attribute ) -> Option < Symbol > {
0 commit comments