@@ -3,7 +3,7 @@ use crate::config::StripUnconfigured;
3
3
use crate :: configure;
4
4
use crate :: hygiene:: SyntaxContext ;
5
5
use crate :: mbe:: macro_rules:: annotate_err_with_kind;
6
- use crate :: module:: { parse_external_mod , push_directory , Directory , DirectoryOwnership } ;
6
+ use crate :: module:: { mod_dir_path , parse_external_mod , DirOwnership , ParsedExternalMod } ;
7
7
use crate :: placeholders:: { placeholder, PlaceholderExpander } ;
8
8
9
9
use rustc_ast as ast;
@@ -355,16 +355,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
355
355
// FIXME: Avoid visiting the crate as a `Mod` item,
356
356
// make crate a first class expansion target instead.
357
357
pub fn expand_crate ( & mut self , mut krate : ast:: Crate ) -> ast:: Crate {
358
- let mut module = ModuleData {
359
- mod_path : vec ! [ Ident :: from_str( & self . cx. ecfg. crate_name) ] ,
360
- directory : match self . cx . source_map ( ) . span_to_unmapped_path ( krate. span ) {
361
- FileName :: Real ( name) => name. into_local_path ( ) ,
362
- other => PathBuf :: from ( other. to_string ( ) ) ,
363
- } ,
358
+ let file_path = match self . cx . source_map ( ) . span_to_unmapped_path ( krate. span ) {
359
+ FileName :: Real ( name) => name. into_local_path ( ) ,
360
+ other => PathBuf :: from ( other. to_string ( ) ) ,
364
361
} ;
365
- module. directory . pop ( ) ;
366
- self . cx . root_path = module. directory . clone ( ) ;
367
- self . cx . current_expansion . module = Rc :: new ( module) ;
362
+ let dir_path = file_path. parent ( ) . unwrap_or ( & file_path) . to_owned ( ) ;
363
+ self . cx . root_path = dir_path. clone ( ) ;
364
+ self . cx . current_expansion . module = Rc :: new ( ModuleData {
365
+ mod_path : vec ! [ Ident :: from_str( & self . cx. ecfg. crate_name) ] ,
366
+ file_path_stack : vec ! [ file_path] ,
367
+ dir_path,
368
+ } ) ;
368
369
369
370
let krate_item = AstFragment :: Items ( smallvec ! [ P ( ast:: Item {
370
371
attrs: krate. attrs,
@@ -1245,10 +1246,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1245
1246
}
1246
1247
1247
1248
fn visit_block ( & mut self , block : & mut P < Block > ) {
1248
- let old_directory_ownership = self . cx . current_expansion . directory_ownership ;
1249
- self . cx . current_expansion . directory_ownership = DirectoryOwnership :: UnownedViaBlock ;
1249
+ let orig_dir_ownership = mem:: replace (
1250
+ & mut self . cx . current_expansion . dir_ownership ,
1251
+ DirOwnership :: UnownedViaBlock ,
1252
+ ) ;
1250
1253
noop_visit_block ( block, self ) ;
1251
- self . cx . current_expansion . directory_ownership = old_directory_ownership ;
1254
+ self . cx . current_expansion . dir_ownership = orig_dir_ownership ;
1252
1255
}
1253
1256
1254
1257
fn flat_map_item ( & mut self , item : P < ast:: Item > ) -> SmallVec < [ P < ast:: Item > ; 1 ] > {
@@ -1276,63 +1279,76 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1276
1279
} )
1277
1280
}
1278
1281
ast:: ItemKind :: Mod ( _, ref mut mod_kind) if ident != Ident :: invalid ( ) => {
1279
- let sess = & self . cx . sess . parse_sess ;
1280
- let orig_ownership = self . cx . current_expansion . directory_ownership ;
1281
- let mut module = ( * self . cx . current_expansion . module ) . clone ( ) ;
1282
-
1283
- let pushed = & mut false ; // Record `parse_external_mod` pushing so we can pop.
1284
- let dir = Directory { ownership : orig_ownership, path : module. directory } ;
1285
- let Directory { ownership, path } = match mod_kind {
1286
- ModKind :: Loaded ( _, Inline :: Yes , _) => {
1282
+ let ( file_path, dir_path, dir_ownership) = match mod_kind {
1283
+ ModKind :: Loaded ( _, inline, _) => {
1287
1284
// Inline `mod foo { ... }`, but we still need to push directories.
1285
+ assert ! (
1286
+ * inline == Inline :: Yes ,
1287
+ "`mod` item is loaded from a file for the second time"
1288
+ ) ;
1289
+ let ( dir_path, dir_ownership) = mod_dir_path (
1290
+ & self . cx . sess ,
1291
+ ident,
1292
+ & attrs,
1293
+ & self . cx . current_expansion . module ,
1294
+ self . cx . current_expansion . dir_ownership ,
1295
+ ) ;
1288
1296
item. attrs = attrs;
1289
- push_directory ( & self . cx . sess , ident, & item. attrs , dir)
1290
- }
1291
- ModKind :: Loaded ( _, Inline :: No , _) => {
1292
- panic ! ( "`mod` item is loaded from a file for the second time" )
1297
+ ( None , dir_path, dir_ownership)
1293
1298
}
1294
1299
ModKind :: Unloaded => {
1295
1300
// We have an outline `mod foo;` so we need to parse the file.
1296
- let ( items, inner_span, dir) =
1297
- parse_external_mod ( & self . cx . sess , ident, span, dir, & mut attrs, pushed) ;
1301
+ let old_attrs_len = attrs. len ( ) ;
1302
+ let ParsedExternalMod {
1303
+ mut items,
1304
+ inner_span,
1305
+ file_path,
1306
+ dir_path,
1307
+ dir_ownership,
1308
+ } = parse_external_mod (
1309
+ & self . cx . sess ,
1310
+ ident,
1311
+ span,
1312
+ & self . cx . current_expansion . module ,
1313
+ self . cx . current_expansion . dir_ownership ,
1314
+ & mut attrs,
1315
+ ) ;
1298
1316
1299
- let krate =
1300
- ast:: Crate { attrs, items, span : inner_span, proc_macros : vec ! [ ] } ;
1301
1317
if let Some ( extern_mod_loaded) = self . cx . extern_mod_loaded {
1302
- extern_mod_loaded ( & krate , ident) ;
1318
+ ( attrs , items ) = extern_mod_loaded ( ident, attrs , items , inner_span ) ;
1303
1319
}
1304
1320
1305
- * mod_kind = ModKind :: Loaded ( krate. items , Inline :: No , inner_span) ;
1306
- item. attrs = krate. attrs ;
1307
- // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1308
- item = match self . configure ( item) {
1309
- Some ( node) => node,
1310
- None => {
1311
- if * pushed {
1312
- sess. included_mod_stack . borrow_mut ( ) . pop ( ) ;
1313
- }
1314
- return Default :: default ( ) ;
1315
- }
1316
- } ;
1317
- dir
1321
+ * mod_kind = ModKind :: Loaded ( items, Inline :: No , inner_span) ;
1322
+ item. attrs = attrs;
1323
+ if item. attrs . len ( ) > old_attrs_len {
1324
+ // If we loaded an out-of-line module and added some inner attributes,
1325
+ // then we need to re-configure it.
1326
+ // FIXME: Attributes also need to be recollected
1327
+ // for resolution and expansion.
1328
+ item = configure ! ( self , item) ;
1329
+ }
1330
+ ( Some ( file_path) , dir_path, dir_ownership)
1318
1331
}
1319
1332
} ;
1320
1333
1321
1334
// Set the module info before we flat map.
1322
- self . cx . current_expansion . directory_ownership = ownership;
1323
- module. directory = path;
1335
+ let mut module = self . cx . current_expansion . module . with_dir_path ( dir_path) ;
1324
1336
module. mod_path . push ( ident) ;
1337
+ if let Some ( file_path) = file_path {
1338
+ module. file_path_stack . push ( file_path) ;
1339
+ }
1340
+
1325
1341
let orig_module =
1326
1342
mem:: replace ( & mut self . cx . current_expansion . module , Rc :: new ( module) ) ;
1343
+ let orig_dir_ownership =
1344
+ mem:: replace ( & mut self . cx . current_expansion . dir_ownership , dir_ownership) ;
1327
1345
1328
1346
let result = noop_flat_map_item ( item, self ) ;
1329
1347
1330
1348
// Restore the module info.
1349
+ self . cx . current_expansion . dir_ownership = orig_dir_ownership;
1331
1350
self . cx . current_expansion . module = orig_module;
1332
- self . cx . current_expansion . directory_ownership = orig_ownership;
1333
- if * pushed {
1334
- sess. included_mod_stack . borrow_mut ( ) . pop ( ) ;
1335
- }
1351
+
1336
1352
result
1337
1353
}
1338
1354
_ => {
0 commit comments