expand: Move module file path stack from global session to expansion data

Also don't push the paths on the stack directly in `fn parse_external_mod`, return them instead.
This commit is contained in:
Vadim Petrochenkov
2021-02-21 19:15:43 +03:00
parent bc18eb4717
commit 39052c55bb
7 changed files with 80 additions and 70 deletions

View File

@@ -355,16 +355,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
// FIXME: Avoid visiting the crate as a `Mod` item,
// make crate a first class expansion target instead.
pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
let mut module = ModuleData {
mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
directory: match self.cx.source_map().span_to_unmapped_path(krate.span) {
FileName::Real(name) => name.into_local_path(),
other => PathBuf::from(other.to_string()),
},
let file_path = match self.cx.source_map().span_to_unmapped_path(krate.span) {
FileName::Real(name) => name.into_local_path(),
other => PathBuf::from(other.to_string()),
};
module.directory.pop();
self.cx.root_path = module.directory.clone();
self.cx.current_expansion.module = Rc::new(module);
let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
self.cx.root_path = dir_path.clone();
self.cx.current_expansion.module = Rc::new(ModuleData {
mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
file_path_stack: vec![file_path],
dir_path,
});
let krate_item = AstFragment::Items(smallvec![P(ast::Item {
attrs: krate.attrs,
@@ -1276,25 +1277,30 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
})
}
ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => {
let sess = &self.cx.sess.parse_sess;
let orig_ownership = self.cx.current_expansion.directory_ownership;
let mut module = (*self.cx.current_expansion.module).clone();
let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
let dir = Directory { ownership: orig_ownership, path: module.directory };
let Directory { ownership, path } = match mod_kind {
let dir = Directory {
ownership: self.cx.current_expansion.directory_ownership,
path: self.cx.current_expansion.module.dir_path.clone(),
};
let (file_path, Directory { ownership, path }) = match mod_kind {
ModKind::Loaded(_, Inline::Yes, _) => {
// Inline `mod foo { ... }`, but we still need to push directories.
let dir_path = push_directory(&self.cx.sess, ident, &attrs, dir);
item.attrs = attrs;
push_directory(&self.cx.sess, ident, &item.attrs, dir)
(None, dir_path)
}
ModKind::Loaded(_, Inline::No, _) => {
panic!("`mod` item is loaded from a file for the second time")
}
ModKind::Unloaded => {
// We have an outline `mod foo;` so we need to parse the file.
let (items, inner_span, dir) =
parse_external_mod(&self.cx.sess, ident, span, dir, &mut attrs, pushed);
let (items, inner_span, file_path, dir_path) = parse_external_mod(
&self.cx.sess,
ident,
span,
&self.cx.current_expansion.module.file_path_stack,
dir,
&mut attrs,
);
let krate =
ast::Crate { attrs, items, span: inner_span, proc_macros: vec![] };
@@ -1305,34 +1311,29 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
*mod_kind = ModKind::Loaded(krate.items, Inline::No, inner_span);
item.attrs = krate.attrs;
// File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
item = match self.configure(item) {
Some(node) => node,
None => {
if *pushed {
sess.included_mod_stack.borrow_mut().pop();
}
return Default::default();
}
};
dir
item = configure!(self, item);
(Some(file_path), dir_path)
}
};
// Set the module info before we flat map.
self.cx.current_expansion.directory_ownership = ownership;
module.directory = path;
let mut module = self.cx.current_expansion.module.with_dir_path(path);
module.mod_path.push(ident);
if let Some(file_path) = file_path {
module.file_path_stack.push(file_path);
}
let orig_module =
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
let orig_dir_ownership =
mem::replace(&mut self.cx.current_expansion.directory_ownership, ownership);
let result = noop_flat_map_item(item, self);
// Restore the module info.
self.cx.current_expansion.directory_ownership = orig_dir_ownership;
self.cx.current_expansion.module = orig_module;
self.cx.current_expansion.directory_ownership = orig_ownership;
if *pushed {
sess.included_mod_stack.borrow_mut().pop();
}
result
}
_ => {