From f2cbe30ee776f0f47d09e708349640fe5309b181 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 18:59:44 +0100 Subject: [PATCH 01/23] submod_path_from_attr: simplify & document --- src/librustc_parse/parser/module.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index b436f1969bb48..b4e7d0a4cf796 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -179,21 +179,22 @@ impl<'a> Parser<'a> { } } + /// Derive a submodule path from the first found `#[path = "path_string"]`. + /// The provided `dir_path` is joined with the `path_string`. // Public for rustfmt usage. pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option { - if let Some(s) = attr::first_attr_value_str_by_name(attrs, sym::path) { - let s = s.as_str(); + // Extract path string from first `#[path = "path_string"]` attribute. + let path_string = attr::first_attr_value_str_by_name(attrs, sym::path)?; + let path_string = path_string.as_str(); - // On windows, the base path might have the form - // `\\?\foo\bar` in which case it does not tolerate - // mixed `/` and `\` separators, so canonicalize - // `/` to `\`. - #[cfg(windows)] - let s = s.replace("/", "\\"); - Some(dir_path.join(&*s)) - } else { - None - } + // On windows, the base path might have the form + // `\\?\foo\bar` in which case it does not tolerate + // mixed `/` and `\` separators, so canonicalize + // `/` to `\`. + #[cfg(windows)] + let path_string = path_string.replace("/", "\\"); + + Some(dir_path.join(&*path_string)) } /// Returns a path to a module. From 9b3364fe7cfb191f44affac91273a7fe9c00537d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 19:11:47 +0100 Subject: [PATCH 02/23] extract error_cannot_declare_mod_here --- src/librustc_parse/parser/module.rs | 54 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index b4e7d0a4cf796..0f5cbb6103c38 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -142,41 +142,41 @@ impl<'a> Parser<'a> { } Err(err) } - DirectoryOwnership::UnownedViaMod => { - let mut err = - self.struct_span_err(id_sp, "cannot declare a new module at this location"); - if !id_sp.is_dummy() { - let src_path = self.sess.source_map().span_to_filename(id_sp); - if let FileName::Real(src_path) = src_path { - if let Some(stem) = src_path.file_stem() { - let mut dest_path = src_path.clone(); - dest_path.set_file_name(stem); - dest_path.push("mod.rs"); - err.span_note( - id_sp, - &format!( - "maybe move this module `{}` to its own \ - directory via `{}`", - src_path.display(), - dest_path.display() - ), - ); - } - } - } - if paths.path_exists { + DirectoryOwnership::UnownedViaMod => self.error_cannot_declare_mod_here(id_sp, paths), + } + } + + fn error_cannot_declare_mod_here(&self, id_sp: Span, paths: ModulePath) -> PResult<'a, T> { + let mut err = self.struct_span_err(id_sp, "cannot declare a new module at this location"); + if !id_sp.is_dummy() { + if let FileName::Real(src_path) = self.sess.source_map().span_to_filename(id_sp) { + if let Some(stem) = src_path.file_stem() { + let mut dest_path = src_path.clone(); + dest_path.set_file_name(stem); + dest_path.push("mod.rs"); err.span_note( id_sp, &format!( - "... or maybe `use` the module `{}` instead \ - of possibly redeclaring it", - paths.name + "maybe move this module `{}` to its own \ + directory via `{}`", + src_path.display(), + dest_path.display() ), ); } - Err(err) } } + if paths.path_exists { + err.span_note( + id_sp, + &format!( + "... or maybe `use` the module `{}` instead \ + of possibly redeclaring it", + paths.name + ), + ); + } + Err(err) } /// Derive a submodule path from the first found `#[path = "path_string"]`. From 6cb04d9386b118f2296b90e5c643011275b91cee Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 19:15:35 +0100 Subject: [PATCH 03/23] extract error_decl_mod_in_block --- src/librustc_parse/parser/module.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 0f5cbb6103c38..f7f19f8181607 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -129,23 +129,22 @@ impl<'a> Parser<'a> { DirectoryOwnership::Owned { .. } => { paths.result.map_err(|err| self.span_fatal_err(id_sp, err)) } - DirectoryOwnership::UnownedViaBlock => { - let msg = "Cannot declare a non-inline module inside a block \ - unless it has a path attribute"; - let mut err = self.struct_span_err(id_sp, msg); - if paths.path_exists { - let msg = format!( - "Maybe `use` the module `{}` instead of redeclaring it", - paths.name - ); - err.span_note(id_sp, &msg); - } - Err(err) - } + DirectoryOwnership::UnownedViaBlock => self.error_decl_mod_in_block(id_sp, paths), DirectoryOwnership::UnownedViaMod => self.error_cannot_declare_mod_here(id_sp, paths), } } + fn error_decl_mod_in_block(&self, id_sp: Span, paths: ModulePath) -> PResult<'a, T> { + let msg = + "Cannot declare a non-inline module inside a block unless it has a path attribute"; + let mut err = self.struct_span_err(id_sp, msg); + if paths.path_exists { + let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", paths.name); + err.span_note(id_sp, &msg); + } + Err(err) + } + fn error_cannot_declare_mod_here(&self, id_sp: Span, paths: ModulePath) -> PResult<'a, T> { let mut err = self.struct_span_err(id_sp, "cannot declare a new module at this location"); if !id_sp.is_dummy() { From 024af0b13254692596737670d0b6740b63b25fa5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 19:20:31 +0100 Subject: [PATCH 04/23] simplify submod_path --- src/librustc_parse/parser/module.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index f7f19f8181607..aa1437bf43fd1 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -102,20 +102,18 @@ impl<'a> Parser<'a> { id_sp: Span, ) -> PResult<'a, ModulePathSuccess> { if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) { - return Ok(ModulePathSuccess { - directory_ownership: match path.file_name().and_then(|s| s.to_str()) { - // All `#[path]` files are treated as though they are a `mod.rs` file. - // This means that `mod foo;` declarations inside `#[path]`-included - // files are siblings, - // - // Note that this will produce weirdness when a file named `foo.rs` is - // `#[path]` included and contains a `mod foo;` declaration. - // If you encounter this, it's your own darn fault :P - Some(_) => DirectoryOwnership::Owned { relative: None }, - _ => DirectoryOwnership::UnownedViaMod, - }, - path, - }); + let directory_ownership = match path.file_name().and_then(|s| s.to_str()) { + // All `#[path]` files are treated as though they are a `mod.rs` file. + // This means that `mod foo;` declarations inside `#[path]`-included + // files are siblings, + // + // Note that this will produce weirdness when a file named `foo.rs` is + // `#[path]` included and contains a `mod foo;` declaration. + // If you encounter this, it's your own darn fault :P + Some(_) => DirectoryOwnership::Owned { relative: None }, + _ => DirectoryOwnership::UnownedViaMod, + }; + return Ok(ModulePathSuccess { directory_ownership, path }); } let relative = match self.directory.ownership { From 9855b34f9a2bb83ecdebcc4784f3323614c8f9b0 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 19:41:24 +0100 Subject: [PATCH 05/23] submod_path: use id.span --- src/librustc_parse/parser/module.rs | 12 +++++------- .../ui/directory_ownership/macro-expanded-mod.rs | 6 ++++-- .../ui/directory_ownership/macro-expanded-mod.stderr | 9 ++------- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index aa1437bf43fd1..be6b03c522299 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -45,14 +45,13 @@ impl<'a> Parser<'a> { pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { let in_cfg = crate::config::process_configure_mod(self.sess, self.cfg_mods, attrs); - let id_span = self.token.span; let id = self.parse_ident()?; let (module, mut inner_attrs) = if self.eat(&token::Semi) { if in_cfg && self.recurse_into_file_modules { // This mod is in an external file. Let's go get it! let ModulePathSuccess { path, directory_ownership } = - self.submod_path(id, &attrs, id_span)?; - self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)? + self.submod_path(id, &attrs)?; + self.eval_src_mod(path, directory_ownership, id.to_string(), id.span)? } else { (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) } @@ -99,7 +98,6 @@ impl<'a> Parser<'a> { &mut self, id: ast::Ident, outer_attrs: &[Attribute], - id_sp: Span, ) -> PResult<'a, ModulePathSuccess> { if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) { let directory_ownership = match path.file_name().and_then(|s| s.to_str()) { @@ -125,10 +123,10 @@ impl<'a> Parser<'a> { match self.directory.ownership { DirectoryOwnership::Owned { .. } => { - paths.result.map_err(|err| self.span_fatal_err(id_sp, err)) + paths.result.map_err(|err| self.span_fatal_err(id.span, err)) } - DirectoryOwnership::UnownedViaBlock => self.error_decl_mod_in_block(id_sp, paths), - DirectoryOwnership::UnownedViaMod => self.error_cannot_declare_mod_here(id_sp, paths), + DirectoryOwnership::UnownedViaBlock => self.error_decl_mod_in_block(id.span, paths), + DirectoryOwnership::UnownedViaMod => self.error_cannot_declare_mod_here(id.span, paths), } } diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.rs b/src/test/ui/directory_ownership/macro-expanded-mod.rs index 376c1a9cd6627..1066a2ba71209 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.rs +++ b/src/test/ui/directory_ownership/macro-expanded-mod.rs @@ -1,7 +1,9 @@ // Test that macro-expanded non-inline modules behave correctly macro_rules! mod_decl { - ($i:ident) => { mod $i; } //~ ERROR Cannot declare a non-inline module inside a block + ($i:ident) => { + mod $i; + }; } mod macro_expanded_mod_helper { @@ -9,5 +11,5 @@ mod macro_expanded_mod_helper { } fn main() { - mod_decl!(foo); + mod_decl!(foo); //~ ERROR Cannot declare a non-inline module inside a block } diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.stderr b/src/test/ui/directory_ownership/macro-expanded-mod.stderr index c7780c869d635..d9d8a8ffed751 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.stderr +++ b/src/test/ui/directory_ownership/macro-expanded-mod.stderr @@ -1,13 +1,8 @@ error: Cannot declare a non-inline module inside a block unless it has a path attribute - --> $DIR/macro-expanded-mod.rs:4:25 + --> $DIR/macro-expanded-mod.rs:14:15 | -LL | ($i:ident) => { mod $i; } - | ^^ -... LL | mod_decl!(foo); - | --------------- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^^^ error: aborting due to previous error From 3eb86cf08db4f77148a84b4f01b22c8a1538c047 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 20:19:52 +0100 Subject: [PATCH 06/23] extract parse_mod --- src/librustc_parse/parser/module.rs | 35 +++++++++++++++-------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index be6b03c522299..a2afc1b4f799b 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -31,14 +31,10 @@ impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> { let lo = self.token.span; - let krate = Ok(ast::Crate { - attrs: self.parse_inner_attributes()?, - module: self.parse_mod_items(&token::Eof, lo)?, - span: lo.to(self.token.span), - // Filled in by proc_macro_harness::inject() - proc_macros: Vec::new(), - }); - krate + let (module, attrs) = self.parse_mod(&token::Eof)?; + let span = lo.to(self.token.span); + let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`. + Ok(ast::Crate { attrs, module, span, proc_macros }) } /// Parses a `mod { ... }` or `mod ;` item. @@ -60,17 +56,23 @@ impl<'a> Parser<'a> { self.push_directory(id, &attrs); self.expect(&token::OpenDelim(token::Brace))?; - let mod_inner_lo = self.token.span; - let inner_attrs = self.parse_inner_attributes()?; - let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?; + let module = self.parse_mod(&token::CloseDelim(token::Brace))?; self.directory = old_directory; - (module, inner_attrs) + module }; attrs.append(&mut inner_attrs); Ok((id, ItemKind::Mod(module))) } + /// Parses the contents of a module (inner attributes followed by module items). + fn parse_mod(&mut self, term: &TokenKind) -> PResult<'a, (Mod, Vec)> { + let lo = self.token.span; + let attrs = self.parse_inner_attributes()?; + let module = self.parse_mod_items(term, lo)?; + Ok((module, attrs)) + } + /// Given a termination token, parses all of the items in a module. fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> { let mut items = vec![]; @@ -271,12 +273,11 @@ impl<'a> Parser<'a> { let mut p0 = new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp); p0.cfg_mods = self.cfg_mods; - let mod_inner_lo = p0.token.span; - let mod_attrs = p0.parse_inner_attributes()?; - let mut m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?; - m0.inline = false; + let mut module = p0.parse_mod(&token::Eof)?; + module.0.inline = false; + self.sess.included_mod_stack.borrow_mut().pop(); - Ok((m0, mod_attrs)) + Ok(module) } fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { From cbcb550a7470857958814ca97a51ad17d6e1d277 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 19:53:25 +0100 Subject: [PATCH 07/23] extract error_on_circular_module --- src/librustc_parse/parser/module.rs | 30 +++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index a2afc1b4f799b..37279c70491e9 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -257,16 +257,7 @@ impl<'a> Parser<'a> { id_sp: Span, ) -> PResult<'a, (Mod, Vec)> { let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut(); - if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { - let mut err = String::from("circular modules: "); - let len = included_mod_stack.len(); - for p in &included_mod_stack[i..len] { - err.push_str(&p.to_string_lossy()); - err.push_str(" -> "); - } - err.push_str(&path.to_string_lossy()); - return Err(self.struct_span_err(id_sp, &err[..])); - } + self.error_on_circular_module(id_sp, &path, &included_mod_stack)?; included_mod_stack.push(path.clone()); drop(included_mod_stack); @@ -280,6 +271,25 @@ impl<'a> Parser<'a> { Ok(module) } + fn error_on_circular_module( + &self, + span: Span, + path: &Path, + included_mod_stack: &[PathBuf], + ) -> PResult<'a, ()> { + if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { + let mut err = String::from("circular modules: "); + let len = included_mod_stack.len(); + for p in &included_mod_stack[i..len] { + err.push_str(&p.to_string_lossy()); + err.push_str(" -> "); + } + err.push_str(&path.to_string_lossy()); + return Err(self.struct_span_err(span, &err[..])); + } + Ok(()) + } + fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) { self.directory.path.push(&*path.as_str()); From 996449bb413cfd9c051169a56fa13f818b63dc9f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 09:28:46 +0100 Subject: [PATCH 08/23] detach submod_path from Parser --- src/librustc_parse/parser/diagnostics.rs | 43 --- src/librustc_parse/parser/module.rs | 352 +++++++++++++---------- 2 files changed, 193 insertions(+), 202 deletions(-) diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 6587e763d50c5..5a2fe9d62521d 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -40,55 +40,12 @@ pub(super) fn dummy_arg(ident: Ident) -> Param { } pub enum Error { - FileNotFoundForModule { - mod_name: String, - default_path: String, - secondary_path: String, - dir_path: String, - }, - DuplicatePaths { - mod_name: String, - default_path: String, - secondary_path: String, - }, UselessDocComment, } impl Error { fn span_err(self, sp: impl Into, handler: &Handler) -> DiagnosticBuilder<'_> { match self { - Error::FileNotFoundForModule { - ref mod_name, - ref default_path, - ref secondary_path, - ref dir_path, - } => { - let mut err = struct_span_err!( - handler, - sp, - E0583, - "file not found for module `{}`", - mod_name, - ); - err.help(&format!( - "name the file either {} or {} inside the directory \"{}\"", - default_path, secondary_path, dir_path, - )); - err - } - Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => { - let mut err = struct_span_err!( - handler, - sp, - E0584, - "file for module `{}` found at both {} and {}", - mod_name, - default_path, - secondary_path, - ); - err.help("delete or rename one of them to remove the ambiguity"); - err - } Error::UselessDocComment => { let mut err = struct_span_err!( handler, diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 37279c70491e9..5b2a0429ffb49 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -1,4 +1,3 @@ -use super::diagnostics::Error; use super::item::ItemInfo; use super::Parser; @@ -7,18 +6,19 @@ use crate::{new_sub_parser_from_file, DirectoryOwnership}; use rustc_ast::ast::{self, Attribute, Crate, Ident, ItemKind, Mod}; use rustc_ast::attr; use rustc_ast::token::{self, TokenKind}; -use rustc_errors::PResult; -use rustc_span::source_map::{FileName, SourceMap, Span, DUMMY_SP}; +use rustc_errors::{struct_span_err, PResult}; +use rustc_session::parse::ParseSess; +use rustc_span::source_map::{FileName, Span, DUMMY_SP}; use rustc_span::symbol::sym; use std::path::{self, Path, PathBuf}; /// Information about the path to a module. // Public for rustfmt usage. -pub struct ModulePath { +pub struct ModulePath<'a> { name: String, path_exists: bool, - pub result: Result, + pub result: PResult<'a, ModulePathSuccess>, } // Public for rustfmt usage. @@ -45,8 +45,13 @@ impl<'a> Parser<'a> { let (module, mut inner_attrs) = if self.eat(&token::Semi) { if in_cfg && self.recurse_into_file_modules { // This mod is in an external file. Let's go get it! - let ModulePathSuccess { path, directory_ownership } = - self.submod_path(id, &attrs)?; + let ModulePathSuccess { path, directory_ownership } = submod_path( + self.sess, + id, + &attrs, + self.directory.ownership, + &self.directory.path, + )?; self.eval_src_mod(path, directory_ownership, id.to_string(), id.span)? } else { (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) @@ -96,158 +101,6 @@ impl<'a> Parser<'a> { Ok(Mod { inner: inner_lo.to(hi), items, inline: true }) } - fn submod_path( - &mut self, - id: ast::Ident, - outer_attrs: &[Attribute], - ) -> PResult<'a, ModulePathSuccess> { - if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) { - let directory_ownership = match path.file_name().and_then(|s| s.to_str()) { - // All `#[path]` files are treated as though they are a `mod.rs` file. - // This means that `mod foo;` declarations inside `#[path]`-included - // files are siblings, - // - // Note that this will produce weirdness when a file named `foo.rs` is - // `#[path]` included and contains a `mod foo;` declaration. - // If you encounter this, it's your own darn fault :P - Some(_) => DirectoryOwnership::Owned { relative: None }, - _ => DirectoryOwnership::UnownedViaMod, - }; - return Ok(ModulePathSuccess { directory_ownership, path }); - } - - let relative = match self.directory.ownership { - DirectoryOwnership::Owned { relative } => relative, - DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, - }; - let paths = - Parser::default_submod_path(id, relative, &self.directory.path, self.sess.source_map()); - - match self.directory.ownership { - DirectoryOwnership::Owned { .. } => { - paths.result.map_err(|err| self.span_fatal_err(id.span, err)) - } - DirectoryOwnership::UnownedViaBlock => self.error_decl_mod_in_block(id.span, paths), - DirectoryOwnership::UnownedViaMod => self.error_cannot_declare_mod_here(id.span, paths), - } - } - - fn error_decl_mod_in_block(&self, id_sp: Span, paths: ModulePath) -> PResult<'a, T> { - let msg = - "Cannot declare a non-inline module inside a block unless it has a path attribute"; - let mut err = self.struct_span_err(id_sp, msg); - if paths.path_exists { - let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", paths.name); - err.span_note(id_sp, &msg); - } - Err(err) - } - - fn error_cannot_declare_mod_here(&self, id_sp: Span, paths: ModulePath) -> PResult<'a, T> { - let mut err = self.struct_span_err(id_sp, "cannot declare a new module at this location"); - if !id_sp.is_dummy() { - if let FileName::Real(src_path) = self.sess.source_map().span_to_filename(id_sp) { - if let Some(stem) = src_path.file_stem() { - let mut dest_path = src_path.clone(); - dest_path.set_file_name(stem); - dest_path.push("mod.rs"); - err.span_note( - id_sp, - &format!( - "maybe move this module `{}` to its own \ - directory via `{}`", - src_path.display(), - dest_path.display() - ), - ); - } - } - } - if paths.path_exists { - err.span_note( - id_sp, - &format!( - "... or maybe `use` the module `{}` instead \ - of possibly redeclaring it", - paths.name - ), - ); - } - Err(err) - } - - /// Derive a submodule path from the first found `#[path = "path_string"]`. - /// The provided `dir_path` is joined with the `path_string`. - // Public for rustfmt usage. - pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option { - // Extract path string from first `#[path = "path_string"]` attribute. - let path_string = attr::first_attr_value_str_by_name(attrs, sym::path)?; - let path_string = path_string.as_str(); - - // On windows, the base path might have the form - // `\\?\foo\bar` in which case it does not tolerate - // mixed `/` and `\` separators, so canonicalize - // `/` to `\`. - #[cfg(windows)] - let path_string = path_string.replace("/", "\\"); - - Some(dir_path.join(&*path_string)) - } - - /// Returns a path to a module. - // Public for rustfmt usage. - pub fn default_submod_path( - id: ast::Ident, - relative: Option, - dir_path: &Path, - source_map: &SourceMap, - ) -> ModulePath { - // If we're in a foo.rs file instead of a mod.rs file, - // we need to look for submodules in - // `./foo/.rs` and `./foo//mod.rs` rather than - // `./.rs` and `.//mod.rs`. - let relative_prefix_string; - let relative_prefix = if let Some(ident) = relative { - relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR); - &relative_prefix_string - } else { - "" - }; - - let mod_name = id.name.to_string(); - let default_path_str = format!("{}{}.rs", relative_prefix, mod_name); - let secondary_path_str = - format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR); - let default_path = dir_path.join(&default_path_str); - let secondary_path = dir_path.join(&secondary_path_str); - let default_exists = source_map.file_exists(&default_path); - let secondary_exists = source_map.file_exists(&secondary_path); - - let result = match (default_exists, secondary_exists) { - (true, false) => Ok(ModulePathSuccess { - path: default_path, - directory_ownership: DirectoryOwnership::Owned { relative: Some(id) }, - }), - (false, true) => Ok(ModulePathSuccess { - path: secondary_path, - directory_ownership: DirectoryOwnership::Owned { relative: None }, - }), - (false, false) => Err(Error::FileNotFoundForModule { - mod_name: mod_name.clone(), - default_path: default_path_str, - secondary_path: secondary_path_str, - dir_path: dir_path.display().to_string(), - }), - (true, true) => Err(Error::DuplicatePaths { - mod_name: mod_name.clone(), - default_path: default_path_str, - secondary_path: secondary_path_str, - }), - }; - - ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result } - } - /// Reads a module from a source file. fn eval_src_mod( &mut self, @@ -311,3 +164,184 @@ impl<'a> Parser<'a> { } } } + +fn submod_path<'a>( + sess: &'a ParseSess, + id: ast::Ident, + outer_attrs: &[Attribute], + directory_ownership: DirectoryOwnership, + dir_path: &Path, +) -> PResult<'a, ModulePathSuccess> { + if let Some(path) = submod_path_from_attr(outer_attrs, dir_path) { + let directory_ownership = match path.file_name().and_then(|s| s.to_str()) { + // All `#[path]` files are treated as though they are a `mod.rs` file. + // This means that `mod foo;` declarations inside `#[path]`-included + // files are siblings, + // + // Note that this will produce weirdness when a file named `foo.rs` is + // `#[path]` included and contains a `mod foo;` declaration. + // If you encounter this, it's your own darn fault :P + Some(_) => DirectoryOwnership::Owned { relative: None }, + _ => DirectoryOwnership::UnownedViaMod, + }; + return Ok(ModulePathSuccess { directory_ownership, path }); + } + + let relative = match directory_ownership { + DirectoryOwnership::Owned { relative } => relative, + DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, + }; + let ModulePath { path_exists, name, result } = + default_submod_path(sess, id, relative, dir_path); + match directory_ownership { + DirectoryOwnership::Owned { .. } => Ok(result?), + DirectoryOwnership::UnownedViaBlock => { + let _ = result.map_err(|mut err| err.cancel()); + error_decl_mod_in_block(sess, id.span, path_exists, &name) + } + DirectoryOwnership::UnownedViaMod => { + let _ = result.map_err(|mut err| err.cancel()); + error_cannot_declare_mod_here(sess, id.span, path_exists, &name) + } + } +} + +fn error_decl_mod_in_block<'a, T>( + sess: &'a ParseSess, + id_sp: Span, + path_exists: bool, + name: &str, +) -> PResult<'a, T> { + let msg = "Cannot declare a non-inline module inside a block unless it has a path attribute"; + let mut err = sess.span_diagnostic.struct_span_err(id_sp, msg); + if path_exists { + let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", name); + err.span_note(id_sp, &msg); + } + Err(err) +} + +fn error_cannot_declare_mod_here<'a, T>( + sess: &'a ParseSess, + id_sp: Span, + path_exists: bool, + name: &str, +) -> PResult<'a, T> { + let mut err = + sess.span_diagnostic.struct_span_err(id_sp, "cannot declare a new module at this location"); + if !id_sp.is_dummy() { + if let FileName::Real(src_path) = sess.source_map().span_to_filename(id_sp) { + if let Some(stem) = src_path.file_stem() { + let mut dest_path = src_path.clone(); + dest_path.set_file_name(stem); + dest_path.push("mod.rs"); + err.span_note( + id_sp, + &format!( + "maybe move this module `{}` to its own \ + directory via `{}`", + src_path.display(), + dest_path.display() + ), + ); + } + } + } + if path_exists { + err.span_note( + id_sp, + &format!("... or maybe `use` the module `{}` instead of possibly redeclaring it", name), + ); + } + Err(err) +} + +/// Derive a submodule path from the first found `#[path = "path_string"]`. +/// The provided `dir_path` is joined with the `path_string`. +// Public for rustfmt usage. +pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option { + // Extract path string from first `#[path = "path_string"]` attribute. + let path_string = attr::first_attr_value_str_by_name(attrs, sym::path)?; + let path_string = path_string.as_str(); + + // On windows, the base path might have the form + // `\\?\foo\bar` in which case it does not tolerate + // mixed `/` and `\` separators, so canonicalize + // `/` to `\`. + #[cfg(windows)] + let path_string = path_string.replace("/", "\\"); + + Some(dir_path.join(&*path_string)) +} + +/// Returns a path to a module. +// Public for rustfmt usage. +pub fn default_submod_path<'a>( + sess: &'a ParseSess, + id: ast::Ident, + relative: Option, + dir_path: &Path, +) -> ModulePath<'a> { + // If we're in a foo.rs file instead of a mod.rs file, + // we need to look for submodules in + // `./foo/.rs` and `./foo//mod.rs` rather than + // `./.rs` and `.//mod.rs`. + let relative_prefix_string; + let relative_prefix = if let Some(ident) = relative { + relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR); + &relative_prefix_string + } else { + "" + }; + + let mod_name = id.name.to_string(); + let default_path_str = format!("{}{}.rs", relative_prefix, mod_name); + let secondary_path_str = + format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR); + let default_path = dir_path.join(&default_path_str); + let secondary_path = dir_path.join(&secondary_path_str); + let default_exists = sess.source_map().file_exists(&default_path); + let secondary_exists = sess.source_map().file_exists(&secondary_path); + + let result = match (default_exists, secondary_exists) { + (true, false) => Ok(ModulePathSuccess { + path: default_path, + directory_ownership: DirectoryOwnership::Owned { relative: Some(id) }, + }), + (false, true) => Ok(ModulePathSuccess { + path: secondary_path, + directory_ownership: DirectoryOwnership::Owned { relative: None }, + }), + (false, false) => { + let mut err = struct_span_err!( + sess.span_diagnostic, + id.span, + E0583, + "file not found for module `{}`", + mod_name, + ); + err.help(&format!( + "name the file either {} or {} inside the directory \"{}\"", + default_path_str, + secondary_path_str, + dir_path.display(), + )); + Err(err) + } + (true, true) => { + let mut err = struct_span_err!( + sess.span_diagnostic, + id.span, + E0584, + "file for module `{}` found at both {} and {}", + mod_name, + default_path_str, + secondary_path_str, + ); + err.help("delete or rename one of them to remove the ambiguity"); + Err(err) + } + }; + + ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result } +} From 81b3500b2b443a227f3d2e01f6d295c6546c6729 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 09:54:19 +0100 Subject: [PATCH 09/23] decouple push_directory from Parser --- src/librustc_parse/parser/module.rs | 41 ++++++++++++++++------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 5b2a0429ffb49..75162ddfe377a 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -58,7 +58,7 @@ impl<'a> Parser<'a> { } } else { let old_directory = self.directory.clone(); - self.push_directory(id, &attrs); + push_directory(id, &attrs, &mut self.directory.ownership, &mut self.directory.path); self.expect(&token::OpenDelim(token::Brace))?; let module = self.parse_mod(&token::CloseDelim(token::Brace))?; @@ -142,26 +142,31 @@ impl<'a> Parser<'a> { } Ok(()) } +} - fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { - if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) { - self.directory.path.push(&*path.as_str()); - self.directory.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 - // `mod x { ... }` come after the relative extension. - // - // 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 self.directory.ownership { - if let Some(ident) = relative.take() { - // remove the relative offset - self.directory.path.push(&*ident.as_str()); - } +fn push_directory( + id: Ident, + attrs: &[Attribute], + dir_ownership: &mut DirectoryOwnership, + dir_path: &mut PathBuf, +) { + if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) { + dir_path.push(&*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 + // `mod x { ... }` come after the relative extension. + // + // 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 } = dir_ownership { + if let Some(ident) = relative.take() { + // Remove the relative offset. + dir_path.push(&*ident.as_str()); } - self.directory.path.push(&*id.as_str()); } + dir_path.push(&*id.as_str()); } } From f284eb3d3924fe40f67c55bed0aca04ea61d4a2b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 11:06:30 +0100 Subject: [PATCH 10/23] decouple eval_src_mod from Parser --- src/librustc_parse/parser/module.rs | 69 ++++++++++++----------------- 1 file changed, 29 insertions(+), 40 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 75162ddfe377a..782e32b3a51cb 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -52,7 +52,7 @@ impl<'a> Parser<'a> { self.directory.ownership, &self.directory.path, )?; - self.eval_src_mod(path, directory_ownership, id.to_string(), id.span)? + eval_src_mod(self.sess, self.cfg_mods, path, directory_ownership, id)? } else { (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) } @@ -100,48 +100,37 @@ impl<'a> Parser<'a> { Ok(Mod { inner: inner_lo.to(hi), items, inline: true }) } +} - /// Reads a module from a source file. - fn eval_src_mod( - &mut self, - path: PathBuf, - directory_ownership: DirectoryOwnership, - name: String, - id_sp: Span, - ) -> PResult<'a, (Mod, Vec)> { - let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut(); - self.error_on_circular_module(id_sp, &path, &included_mod_stack)?; - included_mod_stack.push(path.clone()); - drop(included_mod_stack); - - let mut p0 = - new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp); - p0.cfg_mods = self.cfg_mods; - let mut module = p0.parse_mod(&token::Eof)?; - module.0.inline = false; - - self.sess.included_mod_stack.borrow_mut().pop(); - Ok(module) - } - - fn error_on_circular_module( - &self, - span: Span, - path: &Path, - included_mod_stack: &[PathBuf], - ) -> PResult<'a, ()> { - if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { - let mut err = String::from("circular modules: "); - let len = included_mod_stack.len(); - for p in &included_mod_stack[i..len] { - err.push_str(&p.to_string_lossy()); - err.push_str(" -> "); - } - err.push_str(&path.to_string_lossy()); - return Err(self.struct_span_err(span, &err[..])); +/// Reads a module from a source file. +fn eval_src_mod<'a>( + sess: &'a ParseSess, + cfg_mods: bool, + path: PathBuf, + dir_ownership: DirectoryOwnership, + id: ast::Ident, +) -> PResult<'a, (Mod, Vec)> { + let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); + if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { + let mut err = String::from("circular modules: "); + for p in &included_mod_stack[i..] { + err.push_str(&p.to_string_lossy()); + err.push_str(" -> "); } - Ok(()) + err.push_str(&path.to_string_lossy()); + return Err(sess.span_diagnostic.struct_span_err(id.span, &err[..])); } + included_mod_stack.push(path.clone()); + drop(included_mod_stack); + + let mut p0 = + new_sub_parser_from_file(sess, &path, dir_ownership, Some(id.to_string()), id.span); + p0.cfg_mods = cfg_mods; + let mut module = p0.parse_mod(&token::Eof)?; + module.0.inline = false; + + sess.included_mod_stack.borrow_mut().pop(); + Ok(module) } fn push_directory( From aff35c4e9e66eb76aa6f0767024e3a54f01732f5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 11:18:26 +0100 Subject: [PATCH 11/23] expand: use push_directory --- src/librustc_expand/expand.rs | 14 +++++++------- src/librustc_parse/parser/mod.rs | 2 +- src/librustc_parse/parser/module.rs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index effa89e8bfb21..d6ea1a3dc1b00 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -18,6 +18,7 @@ use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; use rustc_parse::configure; +use rustc_parse::parser::module; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; use rustc_parse::DirectoryOwnership; @@ -1380,13 +1381,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { module.mod_path.push(item.ident); if inline { - if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) { - self.cx.current_expansion.directory_ownership = - DirectoryOwnership::Owned { relative: None }; - module.directory.push(&*path.as_str()); - } else { - module.directory.push(&*item.ident.as_str()); - } + module::push_directory( + item.ident, + &item.attrs, + &mut self.cx.current_expansion.directory_ownership, + &mut module.directory, + ); } else { let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner); let mut path = match path { diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 74101fef8e39b..99a578f0a8a68 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -1,7 +1,7 @@ pub mod attr; mod expr; mod item; -mod module; +pub mod module; pub use module::{ModulePath, ModulePathSuccess}; mod pat; mod path; diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 782e32b3a51cb..67267a1506892 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -133,7 +133,7 @@ fn eval_src_mod<'a>( Ok(module) } -fn push_directory( +pub fn push_directory( id: Ident, attrs: &[Attribute], dir_ownership: &mut DirectoryOwnership, From 75ad1b8a32b15c8c8b1f8f7c794b4417276e3de8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 12:19:27 +0100 Subject: [PATCH 12/23] de-fatalize outline module parsing --- src/librustc_ast/ast.rs | 2 +- src/librustc_parse/parser/module.rs | 37 +++++++++---------- src/test/ui/mod/mod_file_disambig.rs | 1 + src/test/ui/mod/mod_file_disambig.stderr | 11 +++++- src/test/ui/parser/circular_modules_main.rs | 2 +- .../ui/parser/circular_modules_main.stderr | 14 ++++++- src/test/ui/parser/mod_file_not_exist.rs | 1 + src/test/ui/parser/mod_file_not_exist.stderr | 11 +++++- 8 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 88a96dc6c6966..b139815188318 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -2153,7 +2153,7 @@ impl FnRetTy { /// Module declaration. /// /// E.g., `mod foo;` or `mod foo { .. }`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)] pub struct Mod { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 67267a1506892..a46557b927aaf 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -8,7 +8,7 @@ use rustc_ast::attr; use rustc_ast::token::{self, TokenKind}; use rustc_errors::{struct_span_err, PResult}; use rustc_session::parse::ParseSess; -use rustc_span::source_map::{FileName, Span, DUMMY_SP}; +use rustc_span::source_map::{FileName, Span}; use rustc_span::symbol::sym; use std::path::{self, Path, PathBuf}; @@ -24,7 +24,7 @@ pub struct ModulePath<'a> { // Public for rustfmt usage. pub struct ModulePathSuccess { pub path: PathBuf, - pub directory_ownership: DirectoryOwnership, + pub ownership: DirectoryOwnership, } impl<'a> Parser<'a> { @@ -45,16 +45,13 @@ impl<'a> Parser<'a> { let (module, mut inner_attrs) = if self.eat(&token::Semi) { if in_cfg && self.recurse_into_file_modules { // This mod is in an external file. Let's go get it! - let ModulePathSuccess { path, directory_ownership } = submod_path( - self.sess, - id, - &attrs, - self.directory.ownership, - &self.directory.path, - )?; - eval_src_mod(self.sess, self.cfg_mods, path, directory_ownership, id)? + let dir = &self.directory; + submod_path(self.sess, id, &attrs, dir.ownership, &dir.path) + .and_then(|r| eval_src_mod(self.sess, self.cfg_mods, r.path, r.ownership, id)) + .map_err(|mut err| err.emit()) + .unwrap_or_default() } else { - (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) + Default::default() } } else { let old_directory = self.directory.clone(); @@ -162,12 +159,12 @@ pub fn push_directory( fn submod_path<'a>( sess: &'a ParseSess, id: ast::Ident, - outer_attrs: &[Attribute], - directory_ownership: DirectoryOwnership, + attrs: &[Attribute], + ownership: DirectoryOwnership, dir_path: &Path, ) -> PResult<'a, ModulePathSuccess> { - if let Some(path) = submod_path_from_attr(outer_attrs, dir_path) { - let directory_ownership = match path.file_name().and_then(|s| s.to_str()) { + if let Some(path) = submod_path_from_attr(attrs, dir_path) { + let ownership = match path.file_name().and_then(|s| s.to_str()) { // All `#[path]` files are treated as though they are a `mod.rs` file. // This means that `mod foo;` declarations inside `#[path]`-included // files are siblings, @@ -178,16 +175,16 @@ fn submod_path<'a>( Some(_) => DirectoryOwnership::Owned { relative: None }, _ => DirectoryOwnership::UnownedViaMod, }; - return Ok(ModulePathSuccess { directory_ownership, path }); + return Ok(ModulePathSuccess { ownership, path }); } - let relative = match directory_ownership { + let relative = match ownership { DirectoryOwnership::Owned { relative } => relative, DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, }; let ModulePath { path_exists, name, result } = default_submod_path(sess, id, relative, dir_path); - match directory_ownership { + match ownership { DirectoryOwnership::Owned { .. } => Ok(result?), DirectoryOwnership::UnownedViaBlock => { let _ = result.map_err(|mut err| err.cancel()); @@ -300,11 +297,11 @@ pub fn default_submod_path<'a>( let result = match (default_exists, secondary_exists) { (true, false) => Ok(ModulePathSuccess { path: default_path, - directory_ownership: DirectoryOwnership::Owned { relative: Some(id) }, + ownership: DirectoryOwnership::Owned { relative: Some(id) }, }), (false, true) => Ok(ModulePathSuccess { path: secondary_path, - directory_ownership: DirectoryOwnership::Owned { relative: None }, + ownership: DirectoryOwnership::Owned { relative: None }, }), (false, false) => { let mut err = struct_span_err!( diff --git a/src/test/ui/mod/mod_file_disambig.rs b/src/test/ui/mod/mod_file_disambig.rs index ef203ef082b22..7b182421d34e3 100644 --- a/src/test/ui/mod/mod_file_disambig.rs +++ b/src/test/ui/mod/mod_file_disambig.rs @@ -2,4 +2,5 @@ mod mod_file_disambig_aux; //~ ERROR file for module `mod_file_disambig_aux` fou fn main() { assert_eq!(mod_file_aux::bar(), 10); + //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux` } diff --git a/src/test/ui/mod/mod_file_disambig.stderr b/src/test/ui/mod/mod_file_disambig.stderr index 2b77d866fb30b..230bfa79916df 100644 --- a/src/test/ui/mod/mod_file_disambig.stderr +++ b/src/test/ui/mod/mod_file_disambig.stderr @@ -6,6 +6,13 @@ LL | mod mod_file_disambig_aux; | = help: delete or rename one of them to remove the ambiguity -error: aborting due to previous error +error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux` + --> $DIR/mod_file_disambig.rs:4:16 + | +LL | assert_eq!(mod_file_aux::bar(), 10); + | ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0584`. +Some errors have detailed explanations: E0433, E0584. +For more information about an error, try `rustc --explain E0433`. diff --git a/src/test/ui/parser/circular_modules_main.rs b/src/test/ui/parser/circular_modules_main.rs index b85003bf0910f..1ae36a1f7605e 100644 --- a/src/test/ui/parser/circular_modules_main.rs +++ b/src/test/ui/parser/circular_modules_main.rs @@ -6,5 +6,5 @@ pub fn hi_str() -> String { } fn main() { - circular_modules_hello::say_hello(); + circular_modules_hello::say_hello(); //~ ERROR cannot find function `say_hello` in module } diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr index 33865fb7bca95..ca84f2d285403 100644 --- a/src/test/ui/parser/circular_modules_main.stderr +++ b/src/test/ui/parser/circular_modules_main.stderr @@ -4,5 +4,17 @@ error: circular modules: $DIR/circular_modules_hello.rs -> $DIR/circular_modules LL | mod circular_modules_hello; | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0425]: cannot find function `say_hello` in module `circular_modules_hello` + --> $DIR/circular_modules_main.rs:9:29 + | +LL | circular_modules_hello::say_hello(); + | ^^^^^^^^^ not found in `circular_modules_hello` + | +help: possible candidate is found in another module, you can import it into scope + | +LL | use circular_modules_hello::say_hello; + | + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/parser/mod_file_not_exist.rs b/src/test/ui/parser/mod_file_not_exist.rs index e662c707a38b9..f24b6d5928116 100644 --- a/src/test/ui/parser/mod_file_not_exist.rs +++ b/src/test/ui/parser/mod_file_not_exist.rs @@ -5,4 +5,5 @@ mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` fn main() { assert_eq!(mod_file_aux::bar(), 10); + //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux` } diff --git a/src/test/ui/parser/mod_file_not_exist.stderr b/src/test/ui/parser/mod_file_not_exist.stderr index dadf4b29dcf39..8b7b205157306 100644 --- a/src/test/ui/parser/mod_file_not_exist.stderr +++ b/src/test/ui/parser/mod_file_not_exist.stderr @@ -6,6 +6,13 @@ LL | mod not_a_real_file; | = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR" -error: aborting due to previous error +error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux` + --> $DIR/mod_file_not_exist.rs:7:16 + | +LL | assert_eq!(mod_file_aux::bar(), 10); + | ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0583`. +Some errors have detailed explanations: E0433, E0583. +For more information about an error, try `rustc --explain E0433`. From e0d001e1e07e9a4033e265b951b41b7134e635e4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 12:33:15 +0100 Subject: [PATCH 13/23] extract parse_external_module --- src/librustc_parse/parser/module.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index a46557b927aaf..f7d333158a54a 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -44,12 +44,8 @@ impl<'a> Parser<'a> { let id = self.parse_ident()?; let (module, mut inner_attrs) = if self.eat(&token::Semi) { if in_cfg && self.recurse_into_file_modules { - // This mod is in an external file. Let's go get it! let dir = &self.directory; - submod_path(self.sess, id, &attrs, dir.ownership, &dir.path) - .and_then(|r| eval_src_mod(self.sess, self.cfg_mods, r.path, r.ownership, id)) - .map_err(|mut err| err.emit()) - .unwrap_or_default() + parse_external_module(self.sess, self.cfg_mods, id, dir.ownership, &dir.path, attrs) } else { Default::default() } @@ -99,6 +95,20 @@ impl<'a> Parser<'a> { } } +fn parse_external_module( + sess: &ParseSess, + cfg_mods: bool, + id: ast::Ident, + ownership: DirectoryOwnership, + dir_path: &Path, + attrs: &[Attribute], +) -> (Mod, Vec) { + submod_path(sess, id, &attrs, ownership, dir_path) + .and_then(|r| eval_src_mod(sess, cfg_mods, r.path, r.ownership, id)) + .map_err(|mut err| err.emit()) + .unwrap_or_default() +} + /// Reads a module from a source file. fn eval_src_mod<'a>( sess: &'a ParseSess, From df3792cc9a99ecb585357f5930853c701d703b53 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 13:29:37 +0100 Subject: [PATCH 14/23] extract error_on_circular_module --- src/librustc_parse/parser/module.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index f7d333158a54a..1840436fdca3d 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -118,15 +118,7 @@ fn eval_src_mod<'a>( id: ast::Ident, ) -> PResult<'a, (Mod, Vec)> { let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); - if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { - let mut err = String::from("circular modules: "); - for p in &included_mod_stack[i..] { - err.push_str(&p.to_string_lossy()); - err.push_str(" -> "); - } - err.push_str(&path.to_string_lossy()); - return Err(sess.span_diagnostic.struct_span_err(id.span, &err[..])); - } + error_on_circular_module(sess, id.span, &path, &included_mod_stack)?; included_mod_stack.push(path.clone()); drop(included_mod_stack); @@ -140,6 +132,24 @@ fn eval_src_mod<'a>( Ok(module) } +fn error_on_circular_module<'a>( + sess: &'a ParseSess, + span: Span, + path: &Path, + included_mod_stack: &[PathBuf], +) -> PResult<'a, ()> { + if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { + let mut err = String::from("circular modules: "); + for p in &included_mod_stack[i..] { + err.push_str(&p.to_string_lossy()); + err.push_str(" -> "); + } + err.push_str(&path.to_string_lossy()); + return Err(sess.span_diagnostic.struct_span_err(span, &err[..])); + } + Ok(()) +} + pub fn push_directory( id: Ident, attrs: &[Attribute], From a9fd977a41b0b9e91ff0d30e9b5eb17fc82c5e7a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 13:36:20 +0100 Subject: [PATCH 15/23] outline modules: parse -> expand. --- src/librustc_builtin_macros/source_util.rs | 5 +- src/librustc_expand/expand.rs | 77 +++++++++------ src/librustc_expand/mbe/macro_rules.rs | 37 +++----- src/librustc_parse/config.rs | 9 -- src/librustc_parse/lib.rs | 20 ++-- src/librustc_parse/parser/mod.rs | 33 +------ src/librustc_parse/parser/module.rs | 105 ++++++++++----------- src/librustc_parse/parser/stmt.rs | 10 +- 8 files changed, 116 insertions(+), 180 deletions(-) diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs index 5ad72a7443dd2..662bbe6a287a3 100644 --- a/src/librustc_builtin_macros/source_util.rs +++ b/src/librustc_builtin_macros/source_util.rs @@ -5,7 +5,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_expand::base::{self, *}; use rustc_expand::panictry; -use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership}; +use rustc_parse::{self, new_sub_parser_from_file, parser::Parser}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_span::symbol::Symbol; use rustc_span::{self, Pos, Span}; @@ -108,8 +108,7 @@ pub fn expand_include<'cx>( return DummyResult::any(sp); } }; - let directory_ownership = DirectoryOwnership::Owned { relative: None }; - let p = new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp); + let p = new_sub_parser_from_file(cx.parse_sess(), &file, None, sp); struct ExpandResult<'a> { p: Parser<'a>, diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index d6ea1a3dc1b00..f8a1d2c7dbc59 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -18,10 +18,10 @@ use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; use rustc_parse::configure; -use rustc_parse::parser::module; +use rustc_parse::parser::module::{parse_external_mod, push_directory}; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; -use rustc_parse::DirectoryOwnership; +use rustc_parse::{Directory, DirectoryOwnership}; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::{feature_err, ParseSess}; @@ -1360,8 +1360,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_items(); } + let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck. + let ident = item.ident; + match item.kind { ast::ItemKind::Mac(..) => { + item.attrs = attrs; self.check_attributes(&item.attrs); item.and_then(|item| match item.kind { ItemKind::Mac(mac) => self @@ -1373,45 +1377,56 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - ast::ItemKind::Mod(ast::Mod { inner, inline, .. }) - if item.ident != Ident::invalid() => - { - let orig_directory_ownership = self.cx.current_expansion.directory_ownership; + ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => { + let sess = self.cx.parse_sess; + let orig_ownership = self.cx.current_expansion.directory_ownership; let mut module = (*self.cx.current_expansion.module).clone(); - module.mod_path.push(item.ident); - - if inline { - module::push_directory( - item.ident, - &item.attrs, - &mut self.cx.current_expansion.directory_ownership, - &mut module.directory, - ); + + 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 } = if old_mod.inline { + // Inline `mod foo { ... }`, but we still need to push directories. + item.attrs = attrs; + push_directory(ident, &item.attrs, dir) } else { - let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner); - let mut path = match path { - FileName::Real(path) => path, - other => PathBuf::from(other.to_string()), - }; - let directory_ownership = match path.file_name().unwrap().to_str() { - Some("mod.rs") => DirectoryOwnership::Owned { relative: None }, - Some(_) => DirectoryOwnership::Owned { relative: Some(item.ident) }, - None => DirectoryOwnership::UnownedViaMod, + // We have an outline `mod foo;` so we need to parse the file. + let (new_mod, dir) = parse_external_mod(sess, ident, dir, &mut attrs, pushed); + *old_mod = new_mod; + item.attrs = 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(); + } }; - path.pop(); - module.directory = path; - self.cx.current_expansion.directory_ownership = directory_ownership; - } + dir + }; + // Set the module info before we flat map. + self.cx.current_expansion.directory_ownership = ownership; + module.directory = path; + module.mod_path.push(ident); let orig_module = mem::replace(&mut self.cx.current_expansion.module, Rc::new(module)); + let result = noop_flat_map_item(item, self); + + // Restore the module info. self.cx.current_expansion.module = orig_module; - self.cx.current_expansion.directory_ownership = orig_directory_ownership; + self.cx.current_expansion.directory_ownership = orig_ownership; + if *pushed { + sess.included_mod_stack.borrow_mut().pop(); + } result } - - _ => noop_flat_map_item(item, self), + _ => { + item.attrs = attrs; + noop_flat_map_item(item, self) + } } } diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 51b172a21148c..6f3fe9437e207 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -1,4 +1,4 @@ -use crate::base::{DummyResult, ExpansionData, ExtCtxt, MacResult, TTMacroExpander}; +use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; use crate::base::{SyntaxExtension, SyntaxExtensionKind}; use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind}; use crate::mbe; @@ -18,7 +18,6 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder, FatalError}; use rustc_feature::Features; use rustc_parse::parser::Parser; -use rustc_parse::Directory; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::hygiene::Transparency; @@ -182,6 +181,8 @@ fn generic_extension<'cx>( lhses: &[mbe::TokenTree], rhses: &[mbe::TokenTree], ) -> Box { + let sess = cx.parse_sess; + if cx.trace_macros() { let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone())); trace_macros_note(&mut cx.expansions, sp, msg); @@ -209,7 +210,7 @@ fn generic_extension<'cx>( // hacky, but speeds up the `html5ever` benchmark significantly. (Issue // 68836 suggests a more comprehensive but more complex change to deal with // this situation.) - let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); + let parser = parser_from_cx(sess, arg.clone()); for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers @@ -222,14 +223,13 @@ fn generic_extension<'cx>( // This is used so that if a matcher is not `Success(..)`ful, // then the spans which became gated when parsing the unsuccessful matcher // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. - let mut gated_spans_snapshot = - mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut()); + let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut()); match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { Success(named_matches) => { // The matcher was `Success(..)`ful. // Merge the gated spans from parsing the matcher with the pre-existing ones. - cx.parse_sess.gated_spans.merge(gated_spans_snapshot); + sess.gated_spans.merge(gated_spans_snapshot); let rhs = match rhses[i] { // ignore delimiters @@ -258,11 +258,7 @@ fn generic_extension<'cx>( trace_macros_note(&mut cx.expansions, sp, msg); } - let directory = Directory { - path: cx.current_expansion.module.directory.clone(), - ownership: cx.current_expansion.directory_ownership, - }; - let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None); + let mut p = Parser::new(cx.parse_sess(), tts, false, None); p.root_module_name = cx.current_expansion.module.mod_path.last().map(|id| id.to_string()); p.last_type_ascription = cx.current_expansion.prior_type_ascription; @@ -289,7 +285,7 @@ fn generic_extension<'cx>( // The matcher was not `Success(..)`ful. // Restore to the state before snapshotting and maybe try again. - mem::swap(&mut gated_spans_snapshot, &mut cx.parse_sess.gated_spans.spans.borrow_mut()); + mem::swap(&mut gated_spans_snapshot, &mut sess.gated_spans.spans.borrow_mut()); } drop(parser); @@ -309,8 +305,7 @@ fn generic_extension<'cx>( mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], _ => continue, }; - let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); - match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { + match parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt) { Success(_) => { if comma_span.is_dummy() { err.note("you might be missing a comma"); @@ -392,7 +387,7 @@ pub fn compile_declarative_macro( ), ]; - let parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS); + let parser = Parser::new(sess, body, true, rustc_parse::MACRO_ARGUMENTS); let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) { Success(m) => m, Failure(token, msg) => { @@ -1209,16 +1204,8 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } -fn parser_from_cx<'cx>( - current_expansion: &'cx ExpansionData, - sess: &'cx ParseSess, - tts: TokenStream, -) -> Parser<'cx> { - let directory = Directory { - path: current_expansion.module.directory.clone(), - ownership: current_expansion.directory_ownership, - }; - Parser::new(sess, tts, Some(directory), true, true, rustc_parse::MACRO_ARGUMENTS) +fn parser_from_cx<'cx>(sess: &'cx ParseSess, tts: TokenStream) -> Parser<'cx> { + Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS) } /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index f42091e7c296a..632610ae6592f 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -538,12 +538,3 @@ impl<'a> MutVisitor for StripUnconfigured<'a> { fn is_cfg(attr: &Attribute) -> bool { attr.check_name(sym::cfg) } - -/// Process the potential `cfg` attributes on a module. -/// Also determine if the module should be included in this configuration. -pub fn process_configure_mod(sess: &ParseSess, cfg_mods: bool, attrs: &mut Vec) -> bool { - // Don't perform gated feature checking. - let mut strip_unconfigured = StripUnconfigured { sess, features: None }; - strip_unconfigured.process_cfg_attrs(attrs); - !cfg_mods || strip_unconfigured.in_cfg(&attrs) -} diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 25f9f8fd3ad4f..fe36fcec38419 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -2,6 +2,7 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] +#![feature(try_blocks)] use rustc_ast::ast; use rustc_ast::token::{self, Nonterminal, Token}; @@ -118,10 +119,7 @@ pub fn maybe_new_parser_from_source_str( name: FileName, source: String, ) -> Result, Vec> { - let mut parser = - maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))?; - parser.recurse_into_file_modules = false; - Ok(parser) + maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source)) } /// Creates a new parser, handling errors as appropriate if the file doesn't exist. @@ -145,12 +143,10 @@ pub fn maybe_new_parser_from_file<'a>( pub fn new_sub_parser_from_file<'a>( sess: &'a ParseSess, path: &Path, - directory_ownership: DirectoryOwnership, module_name: Option, sp: Span, ) -> Parser<'a> { let mut p = source_file_to_parser(sess, file_to_source_file(sess, path, Some(sp))); - p.directory.ownership = directory_ownership; p.root_module_name = module_name; p } @@ -257,7 +253,7 @@ pub fn stream_to_parser<'a>( stream: TokenStream, subparser_name: Option<&'static str>, ) -> Parser<'a> { - Parser::new(sess, stream, None, true, false, subparser_name) + Parser::new(sess, stream, false, subparser_name) } /// Given a stream, the `ParseSess` and the base directory, produces a parser. @@ -271,12 +267,8 @@ pub fn stream_to_parser<'a>( /// The main usage of this function is outside of rustc, for those who uses /// librustc_ast as a library. Please do not remove this function while refactoring /// just because it is not used in rustc codebase! -pub fn stream_to_parser_with_base_dir<'a>( - sess: &'a ParseSess, - stream: TokenStream, - base_dir: Directory, -) -> Parser<'a> { - Parser::new(sess, stream, Some(base_dir), true, false, None) +pub fn stream_to_parser_with_base_dir<'a>(sess: &'a ParseSess, stream: TokenStream) -> Parser<'a> { + Parser::new(sess, stream, false, None) } /// Runs the given subparser `f` on the tokens of the given `attr`'s item. @@ -286,7 +278,7 @@ pub fn parse_in<'a, T>( name: &'static str, mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, T> { - let mut parser = Parser::new(sess, tts, None, false, false, Some(name)); + let mut parser = Parser::new(sess, tts, false, Some(name)); let result = f(&mut parser)?; if parser.token != token::Eof { parser.unexpected()?; diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 99a578f0a8a68..a182382cfe306 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -13,7 +13,6 @@ mod stmt; use diagnostics::Error; use crate::lexer::UnmatchedBrace; -use crate::{Directory, DirectoryOwnership}; use log::debug; use rustc_ast::ast::DUMMY_NODE_ID; @@ -28,11 +27,9 @@ use rustc_ast::util::comments::{doc_comment_style, strip_doc_comment_decoration} use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult}; use rustc_session::parse::ParseSess; -use rustc_span::source_map::respan; +use rustc_span::source_map::{respan, Span, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::{FileName, Span, DUMMY_SP}; -use std::path::PathBuf; use std::{cmp, mem, slice}; bitflags::bitflags! { @@ -104,11 +101,6 @@ pub struct Parser<'a> { /// this also includes edition checks for edition-specific keyword identifiers. pub normalized_prev_token: Token, restrictions: Restrictions, - /// Used to determine the path to externally loaded source files. - pub(super) directory: Directory, - /// `true` to parse sub-modules in other files. - // Public for rustfmt usage. - pub recurse_into_file_modules: bool, /// Name of the root module this parser originated from. If `None`, then the /// name is not known. This does not change while the parser is descending /// into modules, and sub-parsers have new values for this name. @@ -116,9 +108,6 @@ pub struct Parser<'a> { expected_tokens: Vec, token_cursor: TokenCursor, desugar_doc_comments: bool, - /// `true` we should configure out of line modules as we parse. - // Public for rustfmt usage. - pub cfg_mods: bool, /// This field is used to keep track of how many left angle brackets we have seen. This is /// required in order to detect extra leading left angle brackets (`<` characters) and error /// appropriately. @@ -366,8 +355,6 @@ impl<'a> Parser<'a> { pub fn new( sess: &'a ParseSess, tokens: TokenStream, - directory: Option, - recurse_into_file_modules: bool, desugar_doc_comments: bool, subparser_name: Option<&'static str>, ) -> Self { @@ -378,11 +365,6 @@ impl<'a> Parser<'a> { prev_token: Token::dummy(), normalized_prev_token: Token::dummy(), restrictions: Restrictions::empty(), - recurse_into_file_modules, - directory: Directory { - path: PathBuf::new(), - ownership: DirectoryOwnership::Owned { relative: None }, - }, root_module_name: None, expected_tokens: Vec::new(), token_cursor: TokenCursor { @@ -390,7 +372,6 @@ impl<'a> Parser<'a> { stack: Vec::new(), }, desugar_doc_comments, - cfg_mods: true, unmatched_angle_bracket_count: 0, max_angle_bracket_count: 0, unclosed_delims: Vec::new(), @@ -402,18 +383,6 @@ impl<'a> Parser<'a> { // Make parser point to the first token. parser.bump(); - if let Some(directory) = directory { - parser.directory = directory; - } else if !parser.token.span.is_dummy() { - if let Some(FileName::Real(path)) = - &sess.source_map().lookup_char_pos(parser.token.span.lo()).file.unmapped_path - { - if let Some(directory_path) = path.parent() { - parser.directory.path = directory_path.to_path_buf(); - } - } - } - parser } diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 1840436fdca3d..6a46e22b7feec 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -1,7 +1,7 @@ use super::item::ItemInfo; use super::Parser; -use crate::{new_sub_parser_from_file, DirectoryOwnership}; +use crate::{new_sub_parser_from_file, Directory, DirectoryOwnership}; use rustc_ast::ast::{self, Attribute, Crate, Ident, ItemKind, Mod}; use rustc_ast::attr; @@ -39,25 +39,12 @@ impl<'a> Parser<'a> { /// Parses a `mod { ... }` or `mod ;` item. pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { - let in_cfg = crate::config::process_configure_mod(self.sess, self.cfg_mods, attrs); - let id = self.parse_ident()?; let (module, mut inner_attrs) = if self.eat(&token::Semi) { - if in_cfg && self.recurse_into_file_modules { - let dir = &self.directory; - parse_external_module(self.sess, self.cfg_mods, id, dir.ownership, &dir.path, attrs) - } else { - Default::default() - } + Default::default() } else { - let old_directory = self.directory.clone(); - push_directory(id, &attrs, &mut self.directory.ownership, &mut self.directory.path); - self.expect(&token::OpenDelim(token::Brace))?; - let module = self.parse_mod(&token::CloseDelim(token::Brace))?; - - self.directory = old_directory; - module + self.parse_mod(&token::CloseDelim(token::Brace))? }; attrs.append(&mut inner_attrs); Ok((id, ItemKind::Mod(module))) @@ -95,41 +82,45 @@ impl<'a> Parser<'a> { } } -fn parse_external_module( +pub fn parse_external_mod( sess: &ParseSess, - cfg_mods: bool, - id: ast::Ident, - ownership: DirectoryOwnership, - dir_path: &Path, - attrs: &[Attribute], -) -> (Mod, Vec) { - submod_path(sess, id, &attrs, ownership, dir_path) - .and_then(|r| eval_src_mod(sess, cfg_mods, r.path, r.ownership, id)) - .map_err(|mut err| err.emit()) - .unwrap_or_default() -} - -/// Reads a module from a source file. -fn eval_src_mod<'a>( - sess: &'a ParseSess, - cfg_mods: bool, - path: PathBuf, - dir_ownership: DirectoryOwnership, id: ast::Ident, -) -> PResult<'a, (Mod, Vec)> { - let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); - error_on_circular_module(sess, id.span, &path, &included_mod_stack)?; - included_mod_stack.push(path.clone()); - drop(included_mod_stack); - - let mut p0 = - new_sub_parser_from_file(sess, &path, dir_ownership, Some(id.to_string()), id.span); - p0.cfg_mods = cfg_mods; - let mut module = p0.parse_mod(&token::Eof)?; - module.0.inline = false; + Directory { mut ownership, path }: Directory, + attrs: &mut Vec, + pop_mod_stack: &mut bool, +) -> (Mod, 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. + let mp = submod_path(sess, id, &attrs, ownership, &path)?; + ownership = mp.ownership; + + // Ensure file paths are acyclic. + let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); + error_on_circular_module(sess, id.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); + + // Actually parse the external file as amodule. + let mut p0 = new_sub_parser_from_file(sess, &mp.path, Some(id.to_string()), id.span); + let mut module = p0.parse_mod(&token::Eof)?; + module.0.inline = false; + module + }; + // (1) ...instead, we return a dummy module. + let (module, mut new_attrs) = result.map_err(|mut err| err.emit()).unwrap_or_default(); + attrs.append(&mut new_attrs); + + // Extract the directory path for submodules of `module`. + let path = sess.source_map().span_to_unmapped_path(module.inner); + let mut path = match path { + FileName::Real(path) => path, + other => PathBuf::from(other.to_string()), + }; + path.pop(); - sess.included_mod_stack.borrow_mut().pop(); - Ok(module) + (module, Directory { ownership, path }) } fn error_on_circular_module<'a>( @@ -153,12 +144,11 @@ fn error_on_circular_module<'a>( pub fn push_directory( id: Ident, attrs: &[Attribute], - dir_ownership: &mut DirectoryOwnership, - dir_path: &mut PathBuf, -) { - if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) { - dir_path.push(&*path.as_str()); - *dir_ownership = DirectoryOwnership::Owned { relative: None }; + Directory { mut ownership, mut path }: Directory, +) -> Directory { + if let Some(filename) = attr::first_attr_value_str_by_name(attrs, sym::path) { + path.push(&*filename.as_str()); + 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 @@ -166,14 +156,15 @@ pub 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 } = dir_ownership { + if let DirectoryOwnership::Owned { relative } = &mut ownership { if let Some(ident) = relative.take() { // Remove the relative offset. - dir_path.push(&*ident.as_str()); + path.push(&*ident.as_str()); } } - dir_path.push(&*id.as_str()); + path.push(&*id.as_str()); } + Directory { ownership, path } } fn submod_path<'a>( diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 3864ec3aaa163..f4a852b1532c8 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -4,7 +4,6 @@ use super::pat::GateOr; use super::path::PathStyle; use super::{BlockMode, Parser, Restrictions, SemiColonMode}; use crate::maybe_whole; -use crate::DirectoryOwnership; use rustc_ast::ast; use rustc_ast::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle}; @@ -56,7 +55,7 @@ impl<'a> Parser<'a> { // that starts like a path (1 token), but it fact not a path. // Also, we avoid stealing syntax from `parse_item_`. self.parse_stmt_path_start(lo, attrs)? - } else if let Some(item) = self.parse_stmt_item(attrs.clone())? { + } else if let Some(item) = self.parse_item_common(attrs.clone(), false, true, |_| true)? { // FIXME: Bad copy of attrs self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) } else if self.eat(&token::Semi) { @@ -74,13 +73,6 @@ impl<'a> Parser<'a> { Ok(Some(stmt)) } - fn parse_stmt_item(&mut self, attrs: Vec) -> PResult<'a, Option> { - let old = mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock); - let item = self.parse_item_common(attrs, false, true, |_| true)?; - self.directory.ownership = old; - Ok(item) - } - fn parse_stmt_path_start(&mut self, lo: Span, attrs: Vec) -> PResult<'a, Stmt> { let path = self.parse_path(PathStyle::Expr)?; From e9949222b9ab4ad2ce6a0c1cfb24d8dfed03e291 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 21:50:01 +0100 Subject: [PATCH 16/23] parse: module parsing -> item.rs --- src/librustc_parse/parser/item.rs | 59 ++++++++++++++++++++++++++- src/librustc_parse/parser/module.rs | 62 +---------------------------- 2 files changed, 59 insertions(+), 62 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 01dd2f885ff5e..137f60634a6ef 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -5,7 +5,7 @@ use super::{FollowedByType, Parser, PathStyle}; use crate::maybe_whole; use rustc_ast::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; -use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind}; +use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, Mod}; use rustc_ast::ast::{ Async, Const, Defaultness, IsAuto, PathSegment, Unsafe, UseTree, UseTreeKind, }; @@ -15,7 +15,7 @@ use rustc_ast::ast::{ use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; use rustc_ast::ast::{FnHeader, ForeignItem, Mutability, Visibility, VisibilityKind}; use rustc_ast::ptr::P; -use rustc_ast::token; +use rustc_ast::token::{self, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; @@ -27,6 +27,61 @@ use log::debug; use std::convert::TryFrom; use std::mem; +impl<'a> Parser<'a> { + /// Parses a source module as a crate. This is the main entry point for the parser. + pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> { + let lo = self.token.span; + let (module, attrs) = self.parse_mod(&token::Eof)?; + let span = lo.to(self.token.span); + let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`. + Ok(ast::Crate { attrs, module, span, proc_macros }) + } + + /// Parses a `mod { ... }` or `mod ;` item. + pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + let id = self.parse_ident()?; + let (module, mut inner_attrs) = if self.eat(&token::Semi) { + Default::default() + } else { + self.expect(&token::OpenDelim(token::Brace))?; + self.parse_mod(&token::CloseDelim(token::Brace))? + }; + attrs.append(&mut inner_attrs); + Ok((id, ItemKind::Mod(module))) + } + + /// Parses the contents of a module (inner attributes followed by module items). + pub fn parse_mod(&mut self, term: &TokenKind) -> PResult<'a, (Mod, Vec)> { + let lo = self.token.span; + let attrs = self.parse_inner_attributes()?; + let module = self.parse_mod_items(term, lo)?; + Ok((module, attrs)) + } + + /// Given a termination token, parses all of the items in a module. + fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> { + let mut items = vec![]; + while let Some(item) = self.parse_item()? { + items.push(item); + self.maybe_consume_incorrect_semicolon(&items); + } + + if !self.eat(term) { + let token_str = super::token_descr(&self.token); + if !self.maybe_consume_incorrect_semicolon(&items) { + let msg = &format!("expected item, found {}", token_str); + let mut err = self.struct_span_err(self.token.span, msg); + err.span_label(self.token.span, "expected item"); + return Err(err); + } + } + + let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span }; + + Ok(Mod { inner: inner_lo.to(hi), items, inline: true }) + } +} + pub(super) type ItemInfo = (Ident, ItemKind); impl<'a> Parser<'a> { diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 6a46e22b7feec..1bee676000d73 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -1,11 +1,8 @@ -use super::item::ItemInfo; -use super::Parser; - use crate::{new_sub_parser_from_file, Directory, DirectoryOwnership}; -use rustc_ast::ast::{self, Attribute, Crate, Ident, ItemKind, Mod}; +use rustc_ast::ast::{self, Attribute, Ident, Mod}; use rustc_ast::attr; -use rustc_ast::token::{self, TokenKind}; +use rustc_ast::token; use rustc_errors::{struct_span_err, PResult}; use rustc_session::parse::ParseSess; use rustc_span::source_map::{FileName, Span}; @@ -27,61 +24,6 @@ pub struct ModulePathSuccess { pub ownership: DirectoryOwnership, } -impl<'a> Parser<'a> { - /// Parses a source module as a crate. This is the main entry point for the parser. - pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> { - let lo = self.token.span; - let (module, attrs) = self.parse_mod(&token::Eof)?; - let span = lo.to(self.token.span); - let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`. - Ok(ast::Crate { attrs, module, span, proc_macros }) - } - - /// Parses a `mod { ... }` or `mod ;` item. - pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { - let id = self.parse_ident()?; - let (module, mut inner_attrs) = if self.eat(&token::Semi) { - Default::default() - } else { - self.expect(&token::OpenDelim(token::Brace))?; - self.parse_mod(&token::CloseDelim(token::Brace))? - }; - attrs.append(&mut inner_attrs); - Ok((id, ItemKind::Mod(module))) - } - - /// Parses the contents of a module (inner attributes followed by module items). - fn parse_mod(&mut self, term: &TokenKind) -> PResult<'a, (Mod, Vec)> { - let lo = self.token.span; - let attrs = self.parse_inner_attributes()?; - let module = self.parse_mod_items(term, lo)?; - Ok((module, attrs)) - } - - /// Given a termination token, parses all of the items in a module. - fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> { - let mut items = vec![]; - while let Some(item) = self.parse_item()? { - items.push(item); - self.maybe_consume_incorrect_semicolon(&items); - } - - if !self.eat(term) { - let token_str = super::token_descr(&self.token); - if !self.maybe_consume_incorrect_semicolon(&items) { - let msg = &format!("expected item, found {}", token_str); - let mut err = self.struct_span_err(self.token.span, msg); - err.span_label(self.token.span, "expected item"); - return Err(err); - } - } - - let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span }; - - Ok(Mod { inner: inner_lo.to(hi), items, inline: true }) - } -} - pub fn parse_external_mod( sess: &ParseSess, id: ast::Ident, From 65d072df7a81585d30738305e21157f242f8d486 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 22:10:37 +0100 Subject: [PATCH 17/23] move Directory -> parser::module --- src/librustc_expand/base.rs | 3 ++- src/librustc_expand/expand.rs | 5 +++-- src/librustc_parse/lib.rs | 18 +----------------- src/librustc_parse/parser/module.rs | 21 ++++++++++++++++++--- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index f15e626c2783b..9e8caaa98126d 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -10,7 +10,8 @@ use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::{DiagnosticBuilder, DiagnosticId}; -use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS}; +use rustc_parse::parser::module::DirectoryOwnership; +use rustc_parse::{self, parser, MACRO_ARGUMENTS}; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind}; diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index f8a1d2c7dbc59..5bd9c69e54a0b 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -18,10 +18,11 @@ use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; use rustc_parse::configure; -use rustc_parse::parser::module::{parse_external_mod, push_directory}; +use rustc_parse::parser::module::{ + parse_external_mod, push_directory, Directory, DirectoryOwnership, +}; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; -use rustc_parse::{Directory, DirectoryOwnership}; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::{feature_err, ParseSess}; diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index fe36fcec38419..c1a640e50ba2d 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -13,7 +13,7 @@ use rustc_errors::{Diagnostic, FatalError, Level, PResult}; use rustc_session::parse::ParseSess; use rustc_span::{FileName, SourceFile, Span}; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::str; use log::info; @@ -28,22 +28,6 @@ pub mod validate_attr; #[macro_use] pub mod config; -#[derive(Clone)] -pub struct Directory { - pub path: PathBuf, - pub ownership: DirectoryOwnership, -} - -#[derive(Copy, Clone)] -pub enum DirectoryOwnership { - Owned { - // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`. - relative: Option, - }, - UnownedViaBlock, - UnownedViaMod, -} - // A bunch of utility functions of the form `parse__from_` // where includes crate, expr, item, stmt, tts, and one that // uses a HOF to parse anything, and includes file and diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 1bee676000d73..80e16aef4099b 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -1,8 +1,7 @@ -use crate::{new_sub_parser_from_file, Directory, DirectoryOwnership}; +use crate::new_sub_parser_from_file; use rustc_ast::ast::{self, Attribute, Ident, Mod}; -use rustc_ast::attr; -use rustc_ast::token; +use rustc_ast::{attr, token}; use rustc_errors::{struct_span_err, PResult}; use rustc_session::parse::ParseSess; use rustc_span::source_map::{FileName, Span}; @@ -10,6 +9,22 @@ use rustc_span::symbol::sym; use std::path::{self, Path, PathBuf}; +#[derive(Clone)] +pub struct Directory { + pub path: PathBuf, + pub ownership: DirectoryOwnership, +} + +#[derive(Copy, Clone)] +pub enum DirectoryOwnership { + Owned { + // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`. + relative: Option, + }, + UnownedViaBlock, + UnownedViaMod, +} + /// Information about the path to a module. // Public for rustfmt usage. pub struct ModulePath<'a> { From 1b527aed97291a9a27efca0b0ac21c6a89c91d80 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 22:21:37 +0100 Subject: [PATCH 18/23] {rustc_parse::parser -> rustc_expand}::module --- src/librustc_expand/base.rs | 2 +- src/librustc_expand/expand.rs | 4 +--- src/librustc_expand/lib.rs | 2 ++ src/{librustc_parse/parser => librustc_expand}/module.rs | 7 +++---- src/librustc_parse/lib.rs | 1 - src/librustc_parse/parser/mod.rs | 2 -- 6 files changed, 7 insertions(+), 11 deletions(-) rename src/{librustc_parse/parser => librustc_expand}/module.rs (99%) diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index 9e8caaa98126d..313ff88005295 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -1,4 +1,5 @@ use crate::expand::{self, AstFragment, Invocation}; +use crate::module::DirectoryOwnership; use rustc_ast::ast::{self, Attribute, Name, NodeId, PatKind}; use rustc_ast::mut_visit::{self, MutVisitor}; @@ -10,7 +11,6 @@ use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::{DiagnosticBuilder, DiagnosticId}; -use rustc_parse::parser::module::DirectoryOwnership; use rustc_parse::{self, parser, MACRO_ARGUMENTS}; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 5bd9c69e54a0b..48759315ecc79 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -2,6 +2,7 @@ use crate::base::*; use crate::config::StripUnconfigured; use crate::hygiene::{ExpnData, ExpnId, ExpnKind, SyntaxContext}; use crate::mbe::macro_rules::annotate_err_with_kind; +use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership}; use crate::placeholders::{placeholder, PlaceholderExpander}; use crate::proc_macro::collect_derives; @@ -18,9 +19,6 @@ use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; use rustc_parse::configure; -use rustc_parse::parser::module::{ - parse_external_mod, push_directory, Directory, DirectoryOwnership, -}; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; diff --git a/src/librustc_expand/lib.rs b/src/librustc_expand/lib.rs index f119c956ced04..98d644eb77af4 100644 --- a/src/librustc_expand/lib.rs +++ b/src/librustc_expand/lib.rs @@ -4,6 +4,7 @@ #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] +#![feature(try_blocks)] extern crate proc_macro as pm; @@ -34,6 +35,7 @@ crate use rustc_span::hygiene; pub mod base; pub mod build; pub mod expand; +pub mod module; pub use rustc_parse::config; pub mod proc_macro; diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_expand/module.rs similarity index 99% rename from src/librustc_parse/parser/module.rs rename to src/librustc_expand/module.rs index 80e16aef4099b..960e93f999d04 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_expand/module.rs @@ -1,8 +1,7 @@ -use crate::new_sub_parser_from_file; - use rustc_ast::ast::{self, Attribute, Ident, Mod}; use rustc_ast::{attr, token}; use rustc_errors::{struct_span_err, PResult}; +use rustc_parse::new_sub_parser_from_file; use rustc_session::parse::ParseSess; use rustc_span::source_map::{FileName, Span}; use rustc_span::symbol::sym; @@ -39,7 +38,7 @@ pub struct ModulePathSuccess { pub ownership: DirectoryOwnership, } -pub fn parse_external_mod( +crate fn parse_external_mod( sess: &ParseSess, id: ast::Ident, Directory { mut ownership, path }: Directory, @@ -98,7 +97,7 @@ fn error_on_circular_module<'a>( Ok(()) } -pub fn push_directory( +crate fn push_directory( id: Ident, attrs: &[Attribute], Directory { mut ownership, mut path }: Directory, diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index c1a640e50ba2d..301f3da37b46e 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -2,7 +2,6 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] -#![feature(try_blocks)] use rustc_ast::ast; use rustc_ast::token::{self, Nonterminal, Token}; diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index a182382cfe306..be374aebea18d 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -1,8 +1,6 @@ pub mod attr; mod expr; mod item; -pub mod module; -pub use module::{ModulePath, ModulePathSuccess}; mod pat; mod path; mod ty; From adc3451b5fcafb403bdefbc9e4cc8f66aa15a1ea Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 22:32:25 +0100 Subject: [PATCH 19/23] {rustc_parse -> rustc_expand}::config --- src/{librustc_parse => librustc_expand}/config.rs | 14 +++----------- src/librustc_expand/expand.rs | 2 +- src/librustc_expand/lib.rs | 4 +++- src/librustc_parse/lib.rs | 2 -- src/librustc_parse/validate_attr.rs | 2 +- 5 files changed, 8 insertions(+), 16 deletions(-) rename src/{librustc_parse => librustc_expand}/config.rs (97%) diff --git a/src/librustc_parse/config.rs b/src/librustc_expand/config.rs similarity index 97% rename from src/librustc_parse/config.rs rename to src/librustc_expand/config.rs index 632610ae6592f..1cdd35b52af60 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_expand/config.rs @@ -1,14 +1,5 @@ -//! Process the potential `cfg` attributes on a module. -//! Also determine if the module should be included in this configuration. -//! -//! This module properly belongs in rustc_expand, but for now it's tied into -//! parsing, so we leave it here to avoid complicated out-of-line dependencies. -//! -//! A principled solution to this wrong location would be to implement [#64197]. -//! -//! [#64197]: https://github.com/rust-lang/rust/issues/64197 - -use crate::{parse_in, validate_attr}; +//! Conditional compilation stripping. + use rustc_ast::ast::{self, AttrItem, Attribute, MetaItem}; use rustc_ast::attr::HasAttrs; use rustc_ast::mut_visit::*; @@ -21,6 +12,7 @@ use rustc_feature::{Feature, Features, State as FeatureState}; use rustc_feature::{ ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES, }; +use rustc_parse::{parse_in, validate_attr}; use rustc_session::parse::{feature_err, ParseSess}; use rustc_span::edition::{Edition, ALL_EDITIONS}; use rustc_span::symbol::{sym, Symbol}; diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 48759315ecc79..71aa36176a2ef 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1,5 +1,6 @@ use crate::base::*; use crate::config::StripUnconfigured; +use crate::configure; use crate::hygiene::{ExpnData, ExpnId, ExpnKind, SyntaxContext}; use crate::mbe::macro_rules::annotate_err_with_kind; use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership}; @@ -18,7 +19,6 @@ use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; -use rustc_parse::configure; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; diff --git a/src/librustc_expand/lib.rs b/src/librustc_expand/lib.rs index 98d644eb77af4..0320a275e5d20 100644 --- a/src/librustc_expand/lib.rs +++ b/src/librustc_expand/lib.rs @@ -1,3 +1,4 @@ +#![feature(bool_to_option)] #![feature(cow_is_borrowed)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] @@ -34,9 +35,10 @@ pub use mbe::macro_rules::compile_declarative_macro; crate use rustc_span::hygiene; pub mod base; pub mod build; +#[macro_use] +pub mod config; pub mod expand; pub mod module; -pub use rustc_parse::config; pub mod proc_macro; crate mod mbe; diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 301f3da37b46e..416e0f8cfd9be 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -24,8 +24,6 @@ pub mod parser; use parser::{emit_unclosed_delims, make_unclosed_delims_error, Parser}; pub mod lexer; pub mod validate_attr; -#[macro_use] -pub mod config; // A bunch of utility functions of the form `parse__from_` // where includes crate, expr, item, stmt, tts, and one that diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs index 029aa5ed2baea..2512878ec65be 100644 --- a/src/librustc_parse/validate_attr.rs +++ b/src/librustc_parse/validate_attr.rs @@ -57,7 +57,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta }) } -crate fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) { +pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) { if let ast::MacDelimiter::Parenthesis = delim { return; } From d171e59716f997c76070b0577990b84096f326bf Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 22:48:24 +0100 Subject: [PATCH 20/23] add test for stripped nested outline module --- .../ui/parser/stripped-nested-outline-mod-pass.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/test/ui/parser/stripped-nested-outline-mod-pass.rs diff --git a/src/test/ui/parser/stripped-nested-outline-mod-pass.rs b/src/test/ui/parser/stripped-nested-outline-mod-pass.rs new file mode 100644 index 0000000000000..1b4669a439ffe --- /dev/null +++ b/src/test/ui/parser/stripped-nested-outline-mod-pass.rs @@ -0,0 +1,13 @@ +// Expansion drives parsing, so conditional compilation will strip +// out outline modules and we will never attempt parsing them. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +mod foo { + mod bar { + mod baz; // This was an error before. + } +} From ad0b078ecb6d4e1b6e1f9d7237172d7021a052ef Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 9 Mar 2020 10:35:35 +0100 Subject: [PATCH 21/23] parser/expand: minor cleanup --- src/librustc_expand/mbe/macro_rules.rs | 4 ++-- src/librustc_parse/lib.rs | 15 --------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 6f3fe9437e207..49f38a27acae9 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -258,7 +258,7 @@ fn generic_extension<'cx>( trace_macros_note(&mut cx.expansions, sp, msg); } - let mut p = Parser::new(cx.parse_sess(), tts, false, None); + let mut p = Parser::new(sess, tts, false, None); p.root_module_name = cx.current_expansion.module.mod_path.last().map(|id| id.to_string()); p.last_type_ascription = cx.current_expansion.prior_type_ascription; @@ -1204,7 +1204,7 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } -fn parser_from_cx<'cx>(sess: &'cx ParseSess, tts: TokenStream) -> Parser<'cx> { +fn parser_from_cx(sess: &ParseSess, tts: TokenStream) -> Parser<'_> { Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS) } diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 416e0f8cfd9be..435353fd8993d 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -237,21 +237,6 @@ pub fn stream_to_parser<'a>( Parser::new(sess, stream, false, subparser_name) } -/// Given a stream, the `ParseSess` and the base directory, produces a parser. -/// -/// Use this function when you are creating a parser from the token stream -/// and also care about the current working directory of the parser (e.g., -/// you are trying to resolve modules defined inside a macro invocation). -/// -/// # Note -/// -/// The main usage of this function is outside of rustc, for those who uses -/// librustc_ast as a library. Please do not remove this function while refactoring -/// just because it is not used in rustc codebase! -pub fn stream_to_parser_with_base_dir<'a>(sess: &'a ParseSess, stream: TokenStream) -> Parser<'a> { - Parser::new(sess, stream, false, None) -} - /// Runs the given subparser `f` on the tokens of the given `attr`'s item. pub fn parse_in<'a, T>( sess: &'a ParseSess, From 7df586879671e069ebc30124f445548c8b673c06 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 9 Mar 2020 11:16:00 +0100 Subject: [PATCH 22/23] tweak outline module parsing spans --- src/librustc_expand/expand.rs | 9 ++--- src/librustc_expand/module.rs | 40 ++++++++++--------- src/librustc_parse/parser/item.rs | 2 +- .../directory_ownership/macro-expanded-mod.rs | 4 +- .../macro-expanded-mod.stderr | 9 ++++- .../non-inline-mod-restriction.stderr | 4 +- src/test/ui/error-codes/E0583.stderr | 4 +- .../invalid-module-declaration.stderr | 4 +- .../missing_non_modrs_mod.stderr | 4 +- .../missing_non_modrs_mod_inline.stderr | 4 +- src/test/ui/mod/mod_file_disambig.stderr | 4 +- .../ui/parser/circular_modules_main.stderr | 4 +- src/test/ui/parser/issue-5806.stderr | 4 +- src/test/ui/parser/mod_file_not_exist.stderr | 4 +- .../ui/parser/mod_file_with_path_attr.stderr | 4 +- 15 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 71aa36176a2ef..be92bd6cff398 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1361,6 +1361,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck. let ident = item.ident; + let span = item.span; match item.kind { ast::ItemKind::Mac(..) => { @@ -1368,10 +1369,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.check_attributes(&item.attrs); item.and_then(|item| match item.kind { ItemKind::Mac(mac) => self - .collect( - AstFragmentKind::Items, - InvocationKind::Bang { mac, span: item.span }, - ) + .collect(AstFragmentKind::Items, InvocationKind::Bang { mac, span }) .make_items(), _ => unreachable!(), }) @@ -1389,7 +1387,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { push_directory(ident, &item.attrs, dir) } else { // We have an outline `mod foo;` so we need to parse the file. - let (new_mod, dir) = parse_external_mod(sess, ident, dir, &mut attrs, pushed); + let (new_mod, dir) = + parse_external_mod(sess, ident, span, dir, &mut attrs, pushed); *old_mod = new_mod; item.attrs = attrs; // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. diff --git a/src/librustc_expand/module.rs b/src/librustc_expand/module.rs index 960e93f999d04..99f52e694627e 100644 --- a/src/librustc_expand/module.rs +++ b/src/librustc_expand/module.rs @@ -41,6 +41,7 @@ pub struct ModulePathSuccess { crate fn parse_external_mod( sess: &ParseSess, id: ast::Ident, + span: Span, // The span to blame on errors. Directory { mut ownership, path }: Directory, attrs: &mut Vec, pop_mod_stack: &mut bool, @@ -48,18 +49,18 @@ crate fn parse_external_mod( // 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, &attrs, ownership, &path)?; + let mp = submod_path(sess, id, span, &attrs, ownership, &path)?; ownership = mp.ownership; // Ensure file paths are acyclic. let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); - error_on_circular_module(sess, id.span, &mp.path, &included_mod_stack)?; + error_on_circular_module(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); // Actually parse the external file as amodule. - let mut p0 = new_sub_parser_from_file(sess, &mp.path, Some(id.to_string()), id.span); + let mut p0 = new_sub_parser_from_file(sess, &mp.path, Some(id.to_string()), span); let mut module = p0.parse_mod(&token::Eof)?; module.0.inline = false; module @@ -126,6 +127,7 @@ crate fn push_directory( fn submod_path<'a>( sess: &'a ParseSess, id: ast::Ident, + span: Span, attrs: &[Attribute], ownership: DirectoryOwnership, dir_path: &Path, @@ -150,54 +152,53 @@ fn submod_path<'a>( DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, }; let ModulePath { path_exists, name, result } = - default_submod_path(sess, id, relative, dir_path); + default_submod_path(sess, id, span, relative, dir_path); match ownership { DirectoryOwnership::Owned { .. } => Ok(result?), DirectoryOwnership::UnownedViaBlock => { let _ = result.map_err(|mut err| err.cancel()); - error_decl_mod_in_block(sess, id.span, path_exists, &name) + error_decl_mod_in_block(sess, span, path_exists, &name) } DirectoryOwnership::UnownedViaMod => { let _ = result.map_err(|mut err| err.cancel()); - error_cannot_declare_mod_here(sess, id.span, path_exists, &name) + error_cannot_declare_mod_here(sess, span, path_exists, &name) } } } fn error_decl_mod_in_block<'a, T>( sess: &'a ParseSess, - id_sp: Span, + span: Span, path_exists: bool, name: &str, ) -> PResult<'a, T> { let msg = "Cannot declare a non-inline module inside a block unless it has a path attribute"; - let mut err = sess.span_diagnostic.struct_span_err(id_sp, msg); + let mut err = sess.span_diagnostic.struct_span_err(span, msg); if path_exists { let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", name); - err.span_note(id_sp, &msg); + err.span_note(span, &msg); } Err(err) } fn error_cannot_declare_mod_here<'a, T>( sess: &'a ParseSess, - id_sp: Span, + span: Span, path_exists: bool, name: &str, ) -> PResult<'a, T> { let mut err = - sess.span_diagnostic.struct_span_err(id_sp, "cannot declare a new module at this location"); - if !id_sp.is_dummy() { - if let FileName::Real(src_path) = sess.source_map().span_to_filename(id_sp) { + sess.span_diagnostic.struct_span_err(span, "cannot declare a new module at this location"); + if !span.is_dummy() { + if let FileName::Real(src_path) = sess.source_map().span_to_filename(span) { if let Some(stem) = src_path.file_stem() { let mut dest_path = src_path.clone(); dest_path.set_file_name(stem); dest_path.push("mod.rs"); err.span_note( - id_sp, + span, &format!( - "maybe move this module `{}` to its own \ - directory via `{}`", + "maybe move this module `{}` to its own directory via `{}`", src_path.display(), dest_path.display() ), @@ -207,7 +208,7 @@ fn error_cannot_declare_mod_here<'a, T>( } if path_exists { err.span_note( - id_sp, + span, &format!("... or maybe `use` the module `{}` instead of possibly redeclaring it", name), ); } @@ -237,6 +238,7 @@ pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option( sess: &'a ParseSess, id: ast::Ident, + span: Span, relative: Option, dir_path: &Path, ) -> ModulePath<'a> { @@ -273,7 +275,7 @@ pub fn default_submod_path<'a>( (false, false) => { let mut err = struct_span_err!( sess.span_diagnostic, - id.span, + span, E0583, "file not found for module `{}`", mod_name, @@ -289,7 +291,7 @@ pub fn default_submod_path<'a>( (true, true) => { let mut err = struct_span_err!( sess.span_diagnostic, - id.span, + span, E0584, "file for module `{}` found at both {} and {}", mod_name, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 137f60634a6ef..16d70beac7f85 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -38,7 +38,7 @@ impl<'a> Parser<'a> { } /// Parses a `mod { ... }` or `mod ;` item. - pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { let id = self.parse_ident()?; let (module, mut inner_attrs) = if self.eat(&token::Semi) { Default::default() diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.rs b/src/test/ui/directory_ownership/macro-expanded-mod.rs index 1066a2ba71209..9cb159603a8c5 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.rs +++ b/src/test/ui/directory_ownership/macro-expanded-mod.rs @@ -2,7 +2,7 @@ macro_rules! mod_decl { ($i:ident) => { - mod $i; + mod $i; //~ ERROR Cannot declare a non-inline module inside a block }; } @@ -11,5 +11,5 @@ mod macro_expanded_mod_helper { } fn main() { - mod_decl!(foo); //~ ERROR Cannot declare a non-inline module inside a block + mod_decl!(foo); } diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.stderr b/src/test/ui/directory_ownership/macro-expanded-mod.stderr index d9d8a8ffed751..f90419247c92b 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.stderr +++ b/src/test/ui/directory_ownership/macro-expanded-mod.stderr @@ -1,8 +1,13 @@ error: Cannot declare a non-inline module inside a block unless it has a path attribute - --> $DIR/macro-expanded-mod.rs:14:15 + --> $DIR/macro-expanded-mod.rs:5:9 | +LL | mod $i; + | ^^^^^^^ +... LL | mod_decl!(foo); - | ^^^ + | --------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr index 46acc7e66d8b8..d034942ca5d4c 100644 --- a/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr +++ b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr @@ -1,8 +1,8 @@ error: Cannot declare a non-inline module inside a block unless it has a path attribute - --> $DIR/non-inline-mod-restriction.rs:4:9 + --> $DIR/non-inline-mod-restriction.rs:4:5 | LL | mod foo; - | ^^^ + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0583.stderr b/src/test/ui/error-codes/E0583.stderr index ef7a48bc8a48f..073234475e04d 100644 --- a/src/test/ui/error-codes/E0583.stderr +++ b/src/test/ui/error-codes/E0583.stderr @@ -1,8 +1,8 @@ error[E0583]: file not found for module `module_that_doesnt_exist` - --> $DIR/E0583.rs:1:5 + --> $DIR/E0583.rs:1:1 | LL | mod module_that_doesnt_exist; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: name the file either module_that_doesnt_exist.rs or module_that_doesnt_exist/mod.rs inside the directory "$DIR" diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr index c95df5b4534c1..169fac636f04f 100644 --- a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr +++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr @@ -1,8 +1,8 @@ error[E0583]: file not found for module `baz` - --> $DIR/auxiliary/foo/bar.rs:1:9 + --> $DIR/auxiliary/foo/bar.rs:1:1 | LL | pub mod baz; - | ^^^ + | ^^^^^^^^^^^^ | = help: name the file either bar/baz.rs or bar/baz/mod.rs inside the directory "$DIR/auxiliary/foo" diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr index 98b74e5f5cbca..17ab1c20905da 100644 --- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr @@ -1,8 +1,8 @@ error[E0583]: file not found for module `missing` - --> $DIR/foo.rs:4:5 + --> $DIR/foo.rs:4:1 | LL | mod missing; - | ^^^^^^^ + | ^^^^^^^^^^^^ | = help: name the file either foo/missing.rs or foo/missing/mod.rs inside the directory "$DIR" diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr index 457e8fcccbfb3..e8abc7376f02f 100644 --- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr @@ -1,8 +1,8 @@ error[E0583]: file not found for module `missing` - --> $DIR/foo_inline.rs:4:9 + --> $DIR/foo_inline.rs:4:5 | LL | mod missing; - | ^^^^^^^ + | ^^^^^^^^^^^^ | = help: name the file either missing.rs or missing/mod.rs inside the directory "$DIR/foo_inline/inline" diff --git a/src/test/ui/mod/mod_file_disambig.stderr b/src/test/ui/mod/mod_file_disambig.stderr index 230bfa79916df..490633a3fb0ab 100644 --- a/src/test/ui/mod/mod_file_disambig.stderr +++ b/src/test/ui/mod/mod_file_disambig.stderr @@ -1,8 +1,8 @@ error[E0584]: file for module `mod_file_disambig_aux` found at both mod_file_disambig_aux.rs and mod_file_disambig_aux/mod.rs - --> $DIR/mod_file_disambig.rs:1:5 + --> $DIR/mod_file_disambig.rs:1:1 | LL | mod mod_file_disambig_aux; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: delete or rename one of them to remove the ambiguity diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr index ca84f2d285403..90f81c64835b7 100644 --- a/src/test/ui/parser/circular_modules_main.stderr +++ b/src/test/ui/parser/circular_modules_main.stderr @@ -1,8 +1,8 @@ error: circular modules: $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs - --> $DIR/circular_modules_main.rs:2:5 + --> $DIR/circular_modules_main.rs:2:1 | LL | mod circular_modules_hello; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `say_hello` in module `circular_modules_hello` --> $DIR/circular_modules_main.rs:9:29 diff --git a/src/test/ui/parser/issue-5806.stderr b/src/test/ui/parser/issue-5806.stderr index 6cf902ca86e79..bdb5c91ff91eb 100644 --- a/src/test/ui/parser/issue-5806.stderr +++ b/src/test/ui/parser/issue-5806.stderr @@ -1,8 +1,8 @@ error: couldn't read $DIR/../parser: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE) - --> $DIR/issue-5806.rs:5:5 + --> $DIR/issue-5806.rs:5:1 | LL | mod foo; - | ^^^ + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/mod_file_not_exist.stderr b/src/test/ui/parser/mod_file_not_exist.stderr index 8b7b205157306..ec05eea66c413 100644 --- a/src/test/ui/parser/mod_file_not_exist.stderr +++ b/src/test/ui/parser/mod_file_not_exist.stderr @@ -1,8 +1,8 @@ error[E0583]: file not found for module `not_a_real_file` - --> $DIR/mod_file_not_exist.rs:3:5 + --> $DIR/mod_file_not_exist.rs:3:1 | LL | mod not_a_real_file; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR" diff --git a/src/test/ui/parser/mod_file_with_path_attr.stderr b/src/test/ui/parser/mod_file_with_path_attr.stderr index 004b5d7963a1d..cd1add73d5840 100644 --- a/src/test/ui/parser/mod_file_with_path_attr.stderr +++ b/src/test/ui/parser/mod_file_with_path_attr.stderr @@ -1,8 +1,8 @@ error: couldn't read $DIR/not_a_real_file.rs: $FILE_NOT_FOUND_MSG (os error 2) - --> $DIR/mod_file_with_path_attr.rs:4:5 + --> $DIR/mod_file_with_path_attr.rs:4:1 | LL | mod m; - | ^ + | ^^^^^^ error: aborting due to previous error From 42ab820840639df7e713239f92a5f2bd5d53ec12 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 10 Mar 2020 07:21:40 +0100 Subject: [PATCH 23/23] use pretty-compare-only in a test --- src/test/pretty/issue-12590-a.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/pretty/issue-12590-a.rs b/src/test/pretty/issue-12590-a.rs index 1a9e85c42d8fb..ca1fef83cffc5 100644 --- a/src/test/pretty/issue-12590-a.rs +++ b/src/test/pretty/issue-12590-a.rs @@ -1,4 +1,5 @@ // pp-exact +// pretty-compare-only // The next line should not be expanded