@@ -313,6 +313,8 @@ pub fn Parser<'a>(
313
313
obsolete_set : HashSet :: new ( ) ,
314
314
mod_path_stack : Vec :: new ( ) ,
315
315
open_braces : Vec :: new ( ) ,
316
+ owns_directory : true ,
317
+ root_module_name : None ,
316
318
}
317
319
}
318
320
@@ -342,6 +344,13 @@ pub struct Parser<'a> {
342
344
pub mod_path_stack : Vec < InternedString > ,
343
345
/// Stack of spans of open delimiters. Used for error message.
344
346
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 > ,
345
354
}
346
355
347
356
fn is_plain_ident_or_underscore ( t : & token:: Token ) -> bool {
@@ -4179,9 +4188,12 @@ impl<'a> Parser<'a> {
4179
4188
self . push_mod_path ( id, outer_attrs) ;
4180
4189
self . expect ( & token:: LBRACE ) ;
4181
4190
let mod_inner_lo = self . span . lo ;
4191
+ let old_owns_directory = self . owns_directory ;
4192
+ self . owns_directory = true ;
4182
4193
let ( inner, next) = self . parse_inner_attrs_and_next ( ) ;
4183
4194
let m = self . parse_mod_items ( token:: RBRACE , next, mod_inner_lo) ;
4184
4195
self . expect ( & token:: RBRACE ) ;
4196
+ self . owns_directory = old_owns_directory;
4185
4197
self . pop_mod_path ( ) ;
4186
4198
( id, ItemMod ( m) , Some ( inner) )
4187
4199
}
@@ -4211,21 +4223,42 @@ impl<'a> Parser<'a> {
4211
4223
prefix. pop ( ) ;
4212
4224
let mod_path = Path :: new ( "." ) . join_many ( self . mod_path_stack . as_slice ( ) ) ;
4213
4225
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 (
4215
4228
outer_attrs, "path" ) {
4216
- Some ( d) => dir_path. join ( d) ,
4229
+ Some ( d) => ( dir_path. join ( d) , true ) ,
4217
4230
None => {
4218
- let mod_string = token:: get_ident ( id) ;
4219
4231
let mod_name = mod_string. get ( ) . to_owned ( ) ;
4220
4232
let default_path_str = mod_name + ".rs" ;
4221
4233
let secondary_path_str = mod_name + "/mod.rs" ;
4222
4234
let default_path = dir_path. join ( default_path_str. as_slice ( ) ) ;
4223
4235
let secondary_path = dir_path. join ( secondary_path_str. as_slice ( ) ) ;
4224
4236
let default_exists = default_path. exists ( ) ;
4225
4237
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
+
4226
4259
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 ) ,
4229
4262
( false , false ) => {
4230
4263
self . span_fatal ( id_sp, format ! ( "file not found for module `{}`" , mod_name) ) ;
4231
4264
}
@@ -4238,11 +4271,14 @@ impl<'a> Parser<'a> {
4238
4271
}
4239
4272
} ;
4240
4273
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)
4242
4276
}
4243
4277
4244
4278
fn eval_src_mod_from_path ( & mut self ,
4245
4279
path : Path ,
4280
+ owns_directory : bool ,
4281
+ name : StrBuf ,
4246
4282
id_sp : Span ) -> ( ast:: Item_ , Vec < ast:: Attribute > ) {
4247
4283
let mut included_mod_stack = self . sess . included_mod_stack . borrow_mut ( ) ;
4248
4284
match included_mod_stack. iter ( ) . position ( |p| * p == path) {
@@ -4265,6 +4301,8 @@ impl<'a> Parser<'a> {
4265
4301
new_sub_parser_from_file ( self . sess ,
4266
4302
self . cfg . clone ( ) ,
4267
4303
& path,
4304
+ owns_directory,
4305
+ Some ( name) ,
4268
4306
id_sp) ;
4269
4307
let mod_inner_lo = p0. span . lo ;
4270
4308
let ( mod_attrs, next) = p0. parse_inner_attrs_and_next ( ) ;
0 commit comments