diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2021-02-22 18:58:45 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2021-03-05 01:33:43 +0300 |
| commit | 3d0b622ab7ae3f803d757f73f2a9a7c857d771bb (patch) | |
| tree | 1ebea1b273a36d9c7dd155126e89b87d90d4dd97 | |
| parent | 5bdf81d5fa7ada2274617ebfa97e6bd157ae5a52 (diff) | |
| download | rust-3d0b622ab7ae3f803d757f73f2a9a7c857d771bb.tar.gz rust-3d0b622ab7ae3f803d757f73f2a9a7c857d771bb.zip | |
expand: Less path cloning during module loading
| -rw-r--r-- | compiler/rustc_expand/src/expand.rs | 36 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/module.rs | 52 |
2 files changed, 51 insertions, 37 deletions
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 8d633afacf4..a81bc381c50 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -3,7 +3,7 @@ use crate::config::StripUnconfigured; use crate::configure; use crate::hygiene::SyntaxContext; use crate::mbe::macro_rules::annotate_err_with_kind; -use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership}; +use crate::module::{parse_external_mod, push_directory, DirectoryOwnership, ParsedExternalMod}; use crate::placeholders::{placeholder, PlaceholderExpander}; use rustc_ast as ast; @@ -1277,28 +1277,36 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { }) } ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => { - 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 { + let (file_path, dir_path, dir_ownership) = 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); + let (dir_path, dir_ownership) = push_directory( + &self.cx.sess, + ident, + &attrs, + &self.cx.current_expansion.module, + self.cx.current_expansion.directory_ownership, + ); item.attrs = attrs; - (None, dir_path) + (None, dir_path, dir_ownership) } 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, file_path, dir_path) = parse_external_mod( + let ParsedExternalMod { + items, + inner_span, + file_path, + dir_path, + dir_ownership, + } = parse_external_mod( &self.cx.sess, ident, span, - &self.cx.current_expansion.module.file_path_stack, - dir, + &self.cx.current_expansion.module, + self.cx.current_expansion.directory_ownership, &mut attrs, ); @@ -1312,12 +1320,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { item.attrs = krate.attrs; // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. item = configure!(self, item); - (Some(file_path), dir_path) + (Some(file_path), dir_path, dir_ownership) } }; // Set the module info before we flat map. - let mut module = self.cx.current_expansion.module.with_dir_path(path); + let mut module = self.cx.current_expansion.module.with_dir_path(dir_path); module.mod_path.push(ident); if let Some(file_path) = file_path { module.file_path_stack.push(file_path); @@ -1326,7 +1334,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { 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); + mem::replace(&mut self.cx.current_expansion.directory_ownership, dir_ownership); let result = noop_flat_map_item(item, self); diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index e744ab27e8f..4ba24ace8eb 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -1,3 +1,4 @@ +use crate::base::ModuleData; use rustc_ast::ptr::P; use rustc_ast::{token, Attribute, Item}; use rustc_errors::{struct_span_err, PResult}; @@ -9,12 +10,6 @@ use rustc_span::Span; use std::path::{self, Path, PathBuf}; -#[derive(Clone)] -pub struct Directory { - pub path: PathBuf, - pub ownership: DirectoryOwnership, -} - #[derive(Copy, Clone)] pub enum DirectoryOwnership { Owned { @@ -38,22 +33,30 @@ pub struct ModulePathSuccess { pub ownership: DirectoryOwnership, } +crate struct ParsedExternalMod { + pub items: Vec<P<Item>>, + pub inner_span: Span, + pub file_path: PathBuf, + pub dir_path: PathBuf, + pub dir_ownership: DirectoryOwnership, +} + 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, + module: &ModuleData, + mut dir_ownership: DirectoryOwnership, attrs: &mut Vec<Attribute>, -) -> (Vec<P<Item>>, Span, PathBuf, Directory) { +) -> ParsedExternalMod { // 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. - let mp = submod_path(sess, id, span, &attrs, ownership, &path)?; - ownership = mp.ownership; + let mp = submod_path(sess, id, span, &attrs, dir_ownership, &module.dir_path)?; + dir_ownership = mp.ownership; // Ensure file paths are acyclic. - error_on_circular_module(&sess.parse_sess, span, &mp.path, file_path_stack)?; + error_on_circular_module(&sess.parse_sess, span, &mp.path, &module.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)); @@ -65,9 +68,9 @@ crate fn parse_external_mod( 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 = file_path.parent().unwrap_or(&file_path).to_owned(); + let dir_path = file_path.parent().unwrap_or(&file_path).to_owned(); - (items, inner_span, file_path, Directory { ownership, path }) + ParsedExternalMod { items, inner_span, file_path, dir_path, dir_ownership } } fn error_on_circular_module<'a>( @@ -92,11 +95,13 @@ crate fn push_directory( sess: &Session, id: Ident, attrs: &[Attribute], - Directory { mut ownership, mut path }: Directory, -) -> Directory { - if let Some(filename) = sess.first_attr_value_str_by_name(attrs, sym::path) { - path.push(&*filename.as_str()); - ownership = DirectoryOwnership::Owned { relative: None }; + module: &ModuleData, + mut dir_ownership: DirectoryOwnership, +) -> (PathBuf, DirectoryOwnership) { + let mut dir_path = module.dir_path.clone(); + if let Some(file_path) = sess.first_attr_value_str_by_name(attrs, sym::path) { + dir_path.push(&*file_path.as_str()); + dir_ownership = DirectoryOwnership::Owned { relative: None }; } else { // We have to push on the current module name in the case of relative // paths in order to ensure that any additional module paths from inline @@ -104,15 +109,16 @@ crate fn push_directory( // // For example, a `mod z { ... }` inside `x/y.rs` should set the current // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`. - if let DirectoryOwnership::Owned { relative } = &mut ownership { + if let DirectoryOwnership::Owned { relative } = &mut dir_ownership { if let Some(ident) = relative.take() { // Remove the relative offset. - path.push(&*ident.as_str()); + dir_path.push(&*ident.as_str()); } } - path.push(&*id.as_str()); + dir_path.push(&*id.as_str()); } - Directory { ownership, path } + + (dir_path, dir_ownership) } fn submod_path<'a>( |
