@@ -514,7 +514,10 @@ impl<'a> Parser<'a> {
514514 restrictions : Restrictions :: empty ( ) ,
515515 obsolete_set : HashSet :: new ( ) ,
516516 recurse_into_file_modules,
517- directory : Directory { path : PathBuf :: new ( ) , ownership : DirectoryOwnership :: Owned } ,
517+ directory : Directory {
518+ path : PathBuf :: new ( ) ,
519+ ownership : DirectoryOwnership :: Owned { relative : None }
520+ } ,
518521 root_module_name : None ,
519522 expected_tokens : Vec :: new ( ) ,
520523 token_cursor : TokenCursor {
@@ -5731,7 +5734,7 @@ impl<'a> Parser<'a> {
57315734 fn push_directory ( & mut self , id : Ident , attrs : & [ Attribute ] ) {
57325735 if let Some ( path) = attr:: first_attr_value_str_by_name ( attrs, "path" ) {
57335736 self . directory . path . push ( & path. as_str ( ) ) ;
5734- self . directory . ownership = DirectoryOwnership :: Owned ;
5737+ self . directory . ownership = DirectoryOwnership :: Owned { relative : None } ;
57355738 } else {
57365739 self . directory . path . push ( & id. name . as_str ( ) ) ;
57375740 }
@@ -5742,10 +5745,28 @@ impl<'a> Parser<'a> {
57425745 }
57435746
57445747 /// Returns either a path to a module, or .
5745- pub fn default_submod_path ( id : ast:: Ident , dir_path : & Path , codemap : & CodeMap ) -> ModulePath {
5748+ pub fn default_submod_path (
5749+ id : ast:: Ident ,
5750+ relative : Option < ast:: Ident > ,
5751+ dir_path : & Path ,
5752+ codemap : & CodeMap ) -> ModulePath
5753+ {
5754+ // If we're in a foo.rs file instead of a mod.rs file,
5755+ // we need to look for submodules in
5756+ // `./foo/<id>.rs` and `./foo/<id>/mod.rs` rather than
5757+ // `./<id>.rs` and `./<id>/mod.rs`.
5758+ let relative_prefix_string;
5759+ let relative_prefix = if let Some ( ident) = relative {
5760+ relative_prefix_string = format ! ( "{}{}" , ident. name. as_str( ) , path:: MAIN_SEPARATOR ) ;
5761+ & relative_prefix_string
5762+ } else {
5763+ ""
5764+ } ;
5765+
57465766 let mod_name = id. to_string ( ) ;
5747- let default_path_str = format ! ( "{}.rs" , mod_name) ;
5748- let secondary_path_str = format ! ( "{}{}mod.rs" , mod_name, path:: MAIN_SEPARATOR ) ;
5767+ let default_path_str = format ! ( "{}{}.rs" , relative_prefix, mod_name) ;
5768+ let secondary_path_str = format ! ( "{}{}{}mod.rs" ,
5769+ relative_prefix, mod_name, path:: MAIN_SEPARATOR ) ;
57495770 let default_path = dir_path. join ( & default_path_str) ;
57505771 let secondary_path = dir_path. join ( & secondary_path_str) ;
57515772 let default_exists = codemap. file_exists ( & default_path) ;
@@ -5754,12 +5775,16 @@ impl<'a> Parser<'a> {
57545775 let result = match ( default_exists, secondary_exists) {
57555776 ( true , false ) => Ok ( ModulePathSuccess {
57565777 path : default_path,
5757- directory_ownership : DirectoryOwnership :: UnownedViaMod ( false ) ,
5778+ directory_ownership : DirectoryOwnership :: Owned {
5779+ relative : Some ( id) ,
5780+ } ,
57585781 warn : false ,
57595782 } ) ,
57605783 ( false , true ) => Ok ( ModulePathSuccess {
57615784 path : secondary_path,
5762- directory_ownership : DirectoryOwnership :: Owned ,
5785+ directory_ownership : DirectoryOwnership :: Owned {
5786+ relative : None ,
5787+ } ,
57635788 warn : false ,
57645789 } ) ,
57655790 ( false , false ) => Err ( Error :: FileNotFoundForModule {
@@ -5790,57 +5815,80 @@ impl<'a> Parser<'a> {
57905815 if let Some ( path) = Parser :: submod_path_from_attr ( outer_attrs, & self . directory . path ) {
57915816 return Ok ( ModulePathSuccess {
57925817 directory_ownership : match path. file_name ( ) . and_then ( |s| s. to_str ( ) ) {
5793- Some ( "mod.rs" ) => DirectoryOwnership :: Owned ,
5818+ Some ( "mod.rs" ) => DirectoryOwnership :: Owned { relative : None } ,
5819+ Some ( _) => {
5820+ DirectoryOwnership :: Owned { relative : Some ( id) }
5821+ }
57945822 _ => DirectoryOwnership :: UnownedViaMod ( true ) ,
57955823 } ,
57965824 path,
57975825 warn : false ,
57985826 } ) ;
57995827 }
58005828
5801- let paths = Parser :: default_submod_path ( id, & self . directory . path , self . sess . codemap ( ) ) ;
5829+ let relative = match self . directory . ownership {
5830+ DirectoryOwnership :: Owned { relative } => {
5831+ // Push the usage onto the list of non-mod.rs mod uses.
5832+ // This is used later for feature-gate error reporting.
5833+ if let Some ( cur_file_ident) = relative {
5834+ self . sess
5835+ . non_modrs_mods . borrow_mut ( )
5836+ . push ( ( cur_file_ident, id_sp) ) ;
5837+ }
5838+ relative
5839+ } ,
5840+ DirectoryOwnership :: UnownedViaBlock |
5841+ DirectoryOwnership :: UnownedViaMod ( _) => None ,
5842+ } ;
5843+ let paths = Parser :: default_submod_path (
5844+ id, relative, & self . directory . path , self . sess . codemap ( ) ) ;
58025845
5803- if let DirectoryOwnership :: UnownedViaBlock = self . directory . ownership {
5804- let msg =
5805- "Cannot declare a non-inline module inside a block unless it has a path attribute" ;
5806- let mut err = self . diagnostic ( ) . struct_span_err ( id_sp, msg) ;
5807- if paths. path_exists {
5808- let msg = format ! ( "Maybe `use` the module `{}` instead of redeclaring it" ,
5809- paths. name) ;
5810- err. span_note ( id_sp, & msg) ;
5811- }
5812- Err ( err)
5813- } else if let DirectoryOwnership :: UnownedViaMod ( warn) = self . directory . ownership {
5814- if warn {
5815- if let Ok ( result) = paths. result {
5816- return Ok ( ModulePathSuccess { warn : true , ..result } ) ;
5846+ match self . directory . ownership {
5847+ DirectoryOwnership :: Owned { .. } => {
5848+ paths. result . map_err ( |err| self . span_fatal_err ( id_sp, err) )
5849+ } ,
5850+ DirectoryOwnership :: UnownedViaBlock => {
5851+ let msg =
5852+ "Cannot declare a non-inline module inside a block \
5853+ unless it has a path attribute";
5854+ let mut err = self . diagnostic ( ) . struct_span_err ( id_sp, msg) ;
5855+ if paths. path_exists {
5856+ let msg = format ! ( "Maybe `use` the module `{}` instead of redeclaring it" ,
5857+ paths. name) ;
5858+ err. span_note ( id_sp, & msg) ;
58175859 }
5860+ Err ( err)
58185861 }
5819- let mut err = self . diagnostic ( ) . struct_span_err ( id_sp,
5820- "cannot declare a new module at this location" ) ;
5821- if id_sp != syntax_pos:: DUMMY_SP {
5822- let src_path = self . sess . codemap ( ) . span_to_filename ( id_sp) ;
5823- if let FileName :: Real ( src_path) = src_path {
5824- if let Some ( stem) = src_path. file_stem ( ) {
5825- let mut dest_path = src_path. clone ( ) ;
5826- dest_path. set_file_name ( stem) ;
5827- dest_path. push ( "mod.rs" ) ;
5828- err. span_note ( id_sp,
5862+ DirectoryOwnership :: UnownedViaMod ( warn) => {
5863+ if warn {
5864+ if let Ok ( result) = paths. result {
5865+ return Ok ( ModulePathSuccess { warn : true , ..result } ) ;
5866+ }
5867+ }
5868+ let mut err = self . diagnostic ( ) . struct_span_err ( id_sp,
5869+ "cannot declare a new module at this location" ) ;
5870+ if id_sp != syntax_pos:: DUMMY_SP {
5871+ let src_path = self . sess . codemap ( ) . span_to_filename ( id_sp) ;
5872+ if let FileName :: Real ( src_path) = src_path {
5873+ if let Some ( stem) = src_path. file_stem ( ) {
5874+ let mut dest_path = src_path. clone ( ) ;
5875+ dest_path. set_file_name ( stem) ;
5876+ dest_path. push ( "mod.rs" ) ;
5877+ err. span_note ( id_sp,
58295878 & format ! ( "maybe move this module `{}` to its own \
58305879 directory via `{}`", src_path. display( ) ,
58315880 dest_path. display( ) ) ) ;
5881+ }
58325882 }
58335883 }
5884+ if paths. path_exists {
5885+ err. span_note ( id_sp,
5886+ & format ! ( "... or maybe `use` the module `{}` instead \
5887+ of possibly redeclaring it",
5888+ paths. name) ) ;
5889+ }
5890+ Err ( err)
58345891 }
5835- if paths. path_exists {
5836- err. span_note ( id_sp,
5837- & format ! ( "... or maybe `use` the module `{}` instead \
5838- of possibly redeclaring it",
5839- paths. name) ) ;
5840- }
5841- Err ( err)
5842- } else {
5843- paths. result . map_err ( |err| self . span_fatal_err ( id_sp, err) )
58445892 }
58455893 }
58465894
0 commit comments