@@ -182,13 +182,11 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
182182 item : & ' c ast:: Item ,
183183 sub_mod : Module < ' _ > ,
184184 ) -> Result < ( ) , ModuleResolutionError > {
185- let old_directory = self . directory . clone ( ) ;
186185 let sub_mod_kind = self . peek_sub_mod ( item, & sub_mod) ?;
187186 if let Some ( sub_mod_kind) = sub_mod_kind {
188187 self . insert_sub_mod ( sub_mod_kind. clone ( ) ) ?;
189188 self . visit_sub_mod_inner ( sub_mod, sub_mod_kind) ?;
190189 }
191- self . directory = old_directory;
192190 Ok ( ( ) )
193191 }
194192
@@ -245,34 +243,23 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
245243 path : mod_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ,
246244 ownership : directory_ownership,
247245 } ;
248- self . visit_sub_mod_after_directory_update ( sub_mod , Some ( directory ) )
246+ self . with_directory ( directory , |this| this . visit_mod ( & sub_mod . items ) ) ? ;
249247 }
250248 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 ) ) ? ;
253251 }
254252 SubModKind :: MultiExternal ( mods) => {
255253 for ( mod_path, directory_ownership, sub_mod) in mods {
256254 let directory = Directory {
257255 path : mod_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ,
258256 ownership : directory_ownership,
259257 } ;
260- self . visit_sub_mod_after_directory_update ( sub_mod , Some ( directory ) ) ?;
258+ self . with_directory ( directory , |this| this . visit_mod ( & sub_mod . items ) ) ?;
261259 }
262- Ok ( ( ) )
263260 }
264261 }
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 ( ( ) )
276263 }
277264
278265 /// Find a file path in the filesystem which corresponds to the given module.
@@ -404,31 +391,41 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
404391 }
405392 }
406393
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 {
408395 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
430422 }
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 ,
432429 }
433430 }
434431
@@ -446,8 +443,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
446443 }
447444 let mut result = vec ! [ ] ;
448445 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) ;
451447 if !actual_path. exists ( ) {
452448 continue ;
453449 }
@@ -475,6 +471,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
475471 }
476472 result
477473 }
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+ }
478481}
479482
480483fn path_value ( attr : & ast:: Attribute ) -> Option < Symbol > {
0 commit comments