diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2021-02-21 19:15:43 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2021-03-05 01:33:43 +0300 |
| commit | 39052c55bb0259930dd9e6b0fc27a715793b07c8 (patch) | |
| tree | 39522cbe266f40699b2d97e69a837ab3ce5f495f /compiler | |
| parent | bc18eb471772403de20cd9bc0a836ce1f5e09e98 (diff) | |
| download | rust-39052c55bb0259930dd9e6b0fc27a715793b07c8.tar.gz rust-39052c55bb0259930dd9e6b0fc27a715793b07c8.zip | |
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.
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_builtin_macros/src/source_util.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/base.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/expand.rs | 71 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/module.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_session/src/parse.rs | 4 |
5 files changed, 67 insertions, 59 deletions
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 28efd483c86..98659f15a7e 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -101,7 +101,7 @@ pub fn expand_include<'cx>( None => return DummyResult::any(sp), }; // The file will be added to the code map by the parser - let mut file = match cx.resolve_path(file, sp) { + let file = match cx.resolve_path(file, sp) { Ok(f) => f, Err(mut err) => { err.emit(); @@ -114,10 +114,9 @@ pub fn expand_include<'cx>( // then the path of `bar.rs` should be relative to the directory of `file`. // See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion. // `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained. - file.pop(); + let dir_path = file.parent().unwrap_or(&file).to_owned(); + cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path)); cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None }; - let mod_path = cx.current_expansion.module.mod_path.clone(); - cx.current_expansion.module = Rc::new(ModuleData { mod_path, directory: file }); struct ExpandResult<'a> { p: Parser<'a>, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index ce8103c0f85..a0632522ca0 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -894,10 +894,26 @@ pub trait ResolverExpand { fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>; } -#[derive(Clone)] +#[derive(Clone, Default)] pub struct ModuleData { + /// Path to the module starting from the crate name, like `my_crate::foo::bar`. pub mod_path: Vec<Ident>, - pub directory: PathBuf, + /// Stack of paths to files loaded by out-of-line module items, + /// used to detect and report recursive module inclusions. + pub file_path_stack: Vec<PathBuf>, + /// Directory to search child module files in, + /// often (but not necessarily) the parent of the top file path on the `file_path_stack`. + pub dir_path: PathBuf, +} + +impl ModuleData { + pub fn with_dir_path(&self, dir_path: PathBuf) -> ModuleData { + ModuleData { + mod_path: self.mod_path.clone(), + file_path_stack: self.file_path_stack.clone(), + dir_path, + } + } } #[derive(Clone)] @@ -946,7 +962,7 @@ impl<'a> ExtCtxt<'a> { current_expansion: ExpansionData { id: ExpnId::root(), depth: 0, - module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }), + module: Default::default(), directory_ownership: DirectoryOwnership::Owned { relative: None }, prior_type_ascription: None, }, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index b474cad1242..8d633afacf4 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -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 } _ => { diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 99c1591d40a..55b48e4f6b2 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -42,10 +42,10 @@ crate fn parse_external_mod( sess: &Session, id: Ident, span: Span, // The span to blame on errors. + file_path_stack: &[PathBuf], Directory { mut ownership, path }: Directory, attrs: &mut Vec<Attribute>, - pop_mod_stack: &mut bool, -) -> (Vec<P<Item>>, Span, Directory) { +) -> (Vec<P<Item>>, Span, PathBuf, Directory) { // We bail on the first error, but that error does not cause a fatal error... (1) let result: PResult<'_, _> = try { // Extract the file path and the new ownership. @@ -53,20 +53,16 @@ crate fn parse_external_mod( ownership = mp.ownership; // Ensure file paths are acyclic. - let mut included_mod_stack = sess.parse_sess.included_mod_stack.borrow_mut(); - error_on_circular_module(&sess.parse_sess, span, &mp.path, &included_mod_stack)?; - included_mod_stack.push(mp.path.clone()); - *pop_mod_stack = true; // We have pushed, so notify caller. - drop(included_mod_stack); + error_on_circular_module(&sess.parse_sess, span, &mp.path, file_path_stack)?; // Actually parse the external file as a module. let mut parser = new_parser_from_file(&sess.parse_sess, &mp.path, Some(span)); let (mut inner_attrs, items, inner_span) = parser.parse_mod(&token::Eof)?; attrs.append(&mut inner_attrs); - (items, inner_span) + (items, inner_span, mp.path) }; // (1) ...instead, we return a dummy module. - let (items, inner_span) = result.map_err(|mut err| err.emit()).unwrap_or_default(); + let (items, inner_span, file_path) = result.map_err(|mut err| err.emit()).unwrap_or_default(); // Extract the directory path for submodules of the module. let path = sess.source_map().span_to_unmapped_path(inner_span); @@ -76,18 +72,18 @@ crate fn parse_external_mod( }; path.pop(); - (items, inner_span, Directory { ownership, path }) + (items, inner_span, file_path, Directory { ownership, path }) } fn error_on_circular_module<'a>( sess: &'a ParseSess, span: Span, path: &Path, - included_mod_stack: &[PathBuf], + file_path_stack: &[PathBuf], ) -> PResult<'a, ()> { - if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { + if let Some(i) = file_path_stack.iter().position(|p| *p == path) { let mut err = String::from("circular modules: "); - for p in &included_mod_stack[i..] { + for p in &file_path_stack[i..] { err.push_str(&p.to_string_lossy()); err.push_str(" -> "); } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 81b38347414..592773bfe1b 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -13,7 +13,6 @@ use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{FilePathMapping, SourceMap}; use rustc_span::{MultiSpan, Span, Symbol}; -use std::path::PathBuf; use std::str; /// The set of keys (and, optionally, values) that define the compilation @@ -122,8 +121,6 @@ pub struct ParseSess { pub missing_fragment_specifiers: Lock<FxHashMap<Span, NodeId>>, /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. pub raw_identifier_spans: Lock<Vec<Span>>, - /// Used to determine and report recursive module inclusions. - pub included_mod_stack: Lock<Vec<PathBuf>>, source_map: Lrc<SourceMap>, pub buffered_lints: Lock<Vec<BufferedEarlyLint>>, /// Contains the spans of block expressions that could have been incomplete based on the @@ -157,7 +154,6 @@ impl ParseSess { edition: ExpnId::root().expn_data().edition, missing_fragment_specifiers: Default::default(), raw_identifier_spans: Lock::new(Vec::new()), - included_mod_stack: Lock::new(vec![]), source_map, buffered_lints: Lock::new(vec![]), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), |
