@@ -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