@@ -220,13 +220,11 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
220220 sub_mod : Module < ' _ > ,
221221 from_ast : bool ,
222222 ) -> Result < ( ) , ModuleResolutionError > {
223- let old_directory = self . directory . clone ( ) ;
224223 let sub_mod_kind = self . peek_sub_mod ( item, & sub_mod) ?;
225224 if let Some ( sub_mod_kind) = sub_mod_kind {
226225 self . insert_sub_mod ( sub_mod_kind. clone ( ) ) ?;
227226 self . visit_sub_mod_inner ( sub_mod, sub_mod_kind, from_ast) ?;
228227 }
229- self . directory = old_directory;
230228 Ok ( ( ) )
231229 }
232230
@@ -284,39 +282,30 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
284282 path : mod_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ,
285283 ownership : directory_ownership,
286284 } ;
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 ) ) ? ;
288286 }
289287 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+ } ) ?;
292296 }
293297 SubModKind :: MultiExternal ( mods) => {
294298 for ( mod_path, directory_ownership, sub_mod) in mods {
295299 let directory = Directory {
296300 path : mod_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ,
297301 ownership : directory_ownership,
298302 } ;
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+ } ) ?;
300306 }
301- Ok ( ( ) )
302307 }
303308 }
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- }
320309 Ok ( ( ) )
321310 }
322311
@@ -449,31 +438,41 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
449438 }
450439 }
451440
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 {
453442 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
475469 }
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 ,
477476 }
478477 }
479478
@@ -491,8 +490,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
491490 }
492491 let mut result = vec ! [ ] ;
493492 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) ;
496494 if !actual_path. exists ( ) {
497495 continue ;
498496 }
@@ -520,6 +518,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
520518 }
521519 result
522520 }
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+ }
523528}
524529
525530fn path_value ( attr : & ast:: Attribute ) -> Option < Symbol > {
0 commit comments