@@ -313,6 +313,8 @@ pub fn Parser<'a>(
313313 obsolete_set : HashSet :: new ( ) ,
314314 mod_path_stack : Vec :: new ( ) ,
315315 open_braces : Vec :: new ( ) ,
316+ owns_directory : true ,
317+ root_module_name : None ,
316318 }
317319}
318320
@@ -342,6 +344,13 @@ pub struct Parser<'a> {
342344 pub mod_path_stack : Vec < InternedString > ,
343345 /// Stack of spans of open delimiters. Used for error message.
344346 pub open_braces : Vec < Span > ,
347+ /// Flag if this parser "owns" the directory that it is currently parsing
348+ /// in. This will affect how nested files are looked up.
349+ pub owns_directory : bool ,
350+ /// Name of the root module this parser originated from. If `None`, then the
351+ /// name is not known. This does not change while the parser is descending
352+ /// into modules, and sub-parsers have new values for this name.
353+ pub root_module_name : Option < StrBuf > ,
345354}
346355
347356fn is_plain_ident_or_underscore ( t : & token:: Token ) -> bool {
@@ -4179,9 +4188,12 @@ impl<'a> Parser<'a> {
41794188 self . push_mod_path ( id, outer_attrs) ;
41804189 self . expect ( & token:: LBRACE ) ;
41814190 let mod_inner_lo = self . span . lo ;
4191+ let old_owns_directory = self . owns_directory ;
4192+ self . owns_directory = true ;
41824193 let ( inner, next) = self . parse_inner_attrs_and_next ( ) ;
41834194 let m = self . parse_mod_items ( token:: RBRACE , next, mod_inner_lo) ;
41844195 self . expect ( & token:: RBRACE ) ;
4196+ self . owns_directory = old_owns_directory;
41854197 self . pop_mod_path ( ) ;
41864198 ( id, ItemMod ( m) , Some ( inner) )
41874199 }
@@ -4211,21 +4223,42 @@ impl<'a> Parser<'a> {
42114223 prefix. pop ( ) ;
42124224 let mod_path = Path :: new ( "." ) . join_many ( self . mod_path_stack . as_slice ( ) ) ;
42134225 let dir_path = prefix. join ( & mod_path) ;
4214- let file_path = match :: attr:: first_attr_value_str_by_name (
4226+ let mod_string = token:: get_ident ( id) ;
4227+ let ( file_path, owns_directory) = match :: attr:: first_attr_value_str_by_name (
42154228 outer_attrs, "path" ) {
4216- Some ( d) => dir_path. join ( d) ,
4229+ Some ( d) => ( dir_path. join ( d) , true ) ,
42174230 None => {
4218- let mod_string = token:: get_ident ( id) ;
42194231 let mod_name = mod_string. get ( ) . to_owned ( ) ;
42204232 let default_path_str = mod_name + ".rs" ;
42214233 let secondary_path_str = mod_name + "/mod.rs" ;
42224234 let default_path = dir_path. join ( default_path_str. as_slice ( ) ) ;
42234235 let secondary_path = dir_path. join ( secondary_path_str. as_slice ( ) ) ;
42244236 let default_exists = default_path. exists ( ) ;
42254237 let secondary_exists = secondary_path. exists ( ) ;
4238+
4239+ if !self . owns_directory {
4240+ self . span_err ( id_sp,
4241+ "cannot declare a new module at this location" ) ;
4242+ let this_module = match self . mod_path_stack . last ( ) {
4243+ Some ( name) => name. get ( ) . to_strbuf ( ) ,
4244+ None => self . root_module_name . get_ref ( ) . clone ( ) ,
4245+ } ;
4246+ self . span_note ( id_sp,
4247+ format ! ( "maybe move this module `{0}` \
4248+ to its own directory via \
4249+ `{0}/mod.rs`", this_module) ) ;
4250+ if default_exists || secondary_exists {
4251+ self . span_note ( id_sp,
4252+ format ! ( "... or maybe `use` the module \
4253+ `{}` instead of possibly \
4254+ redeclaring it", mod_name) ) ;
4255+ }
4256+ self . abort_if_errors ( ) ;
4257+ }
4258+
42264259 match ( default_exists, secondary_exists) {
4227- ( true , false ) => default_path,
4228- ( false , true ) => secondary_path,
4260+ ( true , false ) => ( default_path, false ) ,
4261+ ( false , true ) => ( secondary_path, true ) ,
42294262 ( false , false ) => {
42304263 self . span_fatal ( id_sp, format ! ( "file not found for module `{}`" , mod_name) ) ;
42314264 }
@@ -4238,11 +4271,14 @@ impl<'a> Parser<'a> {
42384271 }
42394272 } ;
42404273
4241- self . eval_src_mod_from_path ( file_path, id_sp)
4274+ self . eval_src_mod_from_path ( file_path, owns_directory,
4275+ mod_string. get ( ) . to_strbuf ( ) , id_sp)
42424276 }
42434277
42444278 fn eval_src_mod_from_path ( & mut self ,
42454279 path : Path ,
4280+ owns_directory : bool ,
4281+ name : StrBuf ,
42464282 id_sp : Span ) -> ( ast:: Item_ , Vec < ast:: Attribute > ) {
42474283 let mut included_mod_stack = self . sess . included_mod_stack . borrow_mut ( ) ;
42484284 match included_mod_stack. iter ( ) . position ( |p| * p == path) {
@@ -4265,6 +4301,8 @@ impl<'a> Parser<'a> {
42654301 new_sub_parser_from_file ( self . sess ,
42664302 self . cfg . clone ( ) ,
42674303 & path,
4304+ owns_directory,
4305+ Some ( name) ,
42684306 id_sp) ;
42694307 let mod_inner_lo = p0. span . lo ;
42704308 let ( mod_attrs, next) = p0. parse_inner_attrs_and_next ( ) ;
0 commit comments