@@ -514,7 +514,10 @@ impl<'a> Parser<'a> {
514
514
restrictions : Restrictions :: empty ( ) ,
515
515
obsolete_set : HashSet :: new ( ) ,
516
516
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
+ } ,
518
521
root_module_name : None ,
519
522
expected_tokens : Vec :: new ( ) ,
520
523
token_cursor : TokenCursor {
@@ -5731,7 +5734,7 @@ impl<'a> Parser<'a> {
5731
5734
fn push_directory ( & mut self , id : Ident , attrs : & [ Attribute ] ) {
5732
5735
if let Some ( path) = attr:: first_attr_value_str_by_name ( attrs, "path" ) {
5733
5736
self . directory . path . push ( & path. as_str ( ) ) ;
5734
- self . directory . ownership = DirectoryOwnership :: Owned ;
5737
+ self . directory . ownership = DirectoryOwnership :: Owned { relative : None } ;
5735
5738
} else {
5736
5739
self . directory . path . push ( & id. name . as_str ( ) ) ;
5737
5740
}
@@ -5742,10 +5745,28 @@ impl<'a> Parser<'a> {
5742
5745
}
5743
5746
5744
5747
/// 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
+
5746
5766
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 ) ;
5749
5770
let default_path = dir_path. join ( & default_path_str) ;
5750
5771
let secondary_path = dir_path. join ( & secondary_path_str) ;
5751
5772
let default_exists = codemap. file_exists ( & default_path) ;
@@ -5754,12 +5775,16 @@ impl<'a> Parser<'a> {
5754
5775
let result = match ( default_exists, secondary_exists) {
5755
5776
( true , false ) => Ok ( ModulePathSuccess {
5756
5777
path : default_path,
5757
- directory_ownership : DirectoryOwnership :: UnownedViaMod ( false ) ,
5778
+ directory_ownership : DirectoryOwnership :: Owned {
5779
+ relative : Some ( id) ,
5780
+ } ,
5758
5781
warn : false ,
5759
5782
} ) ,
5760
5783
( false , true ) => Ok ( ModulePathSuccess {
5761
5784
path : secondary_path,
5762
- directory_ownership : DirectoryOwnership :: Owned ,
5785
+ directory_ownership : DirectoryOwnership :: Owned {
5786
+ relative : None ,
5787
+ } ,
5763
5788
warn : false ,
5764
5789
} ) ,
5765
5790
( false , false ) => Err ( Error :: FileNotFoundForModule {
@@ -5790,57 +5815,80 @@ impl<'a> Parser<'a> {
5790
5815
if let Some ( path) = Parser :: submod_path_from_attr ( outer_attrs, & self . directory . path ) {
5791
5816
return Ok ( ModulePathSuccess {
5792
5817
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
+ }
5794
5822
_ => DirectoryOwnership :: UnownedViaMod ( true ) ,
5795
5823
} ,
5796
5824
path,
5797
5825
warn : false ,
5798
5826
} ) ;
5799
5827
}
5800
5828
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 ( ) ) ;
5802
5845
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) ;
5817
5859
}
5860
+ Err ( err)
5818
5861
}
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,
5829
5878
& format ! ( "maybe move this module `{}` to its own \
5830
5879
directory via `{}`", src_path. display( ) ,
5831
5880
dest_path. display( ) ) ) ;
5881
+ }
5832
5882
}
5833
5883
}
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)
5834
5891
}
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) )
5844
5892
}
5845
5893
}
5846
5894
0 commit comments