Skip to content

Commit 4a4e3e6

Browse files
authored
Rollup merge of #82415 - petrochenkov:modin3, r=davidtwco
expand: Refactor module loading This is an accompanying PR to #82399, but they can be landed independently. See individual commits for more details. Anyone should be able to review this equally well because all people actually familiar with this code left the project.
2 parents da74a77 + 1fe2eb8 commit 4a4e3e6

File tree

15 files changed

+295
-292
lines changed

15 files changed

+295
-292
lines changed

compiler/rustc_builtin_macros/src/source_util.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_ast::token;
44
use rustc_ast::tokenstream::TokenStream;
55
use rustc_ast_pretty::pprust;
66
use rustc_expand::base::{self, *};
7-
use rustc_expand::module::DirectoryOwnership;
7+
use rustc_expand::module::DirOwnership;
88
use rustc_parse::parser::{ForceCollect, Parser};
99
use rustc_parse::{self, new_parser_from_file};
1010
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
@@ -101,7 +101,7 @@ pub fn expand_include<'cx>(
101101
None => return DummyResult::any(sp),
102102
};
103103
// The file will be added to the code map by the parser
104-
let mut file = match cx.resolve_path(file, sp) {
104+
let file = match cx.resolve_path(file, sp) {
105105
Ok(f) => f,
106106
Err(mut err) => {
107107
err.emit();
@@ -114,10 +114,9 @@ pub fn expand_include<'cx>(
114114
// then the path of `bar.rs` should be relative to the directory of `file`.
115115
// See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion.
116116
// `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained.
117-
file.pop();
118-
cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None };
119-
let mod_path = cx.current_expansion.module.mod_path.clone();
120-
cx.current_expansion.module = Rc::new(ModuleData { mod_path, directory: file });
117+
let dir_path = file.parent().unwrap_or(&file).to_owned();
118+
cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path));
119+
cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None };
121120

122121
struct ExpandResult<'a> {
123122
p: Parser<'a>,

compiler/rustc_expand/src/base.rs

+28-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use crate::expand::{self, AstFragment, Invocation};
2-
use crate::module::DirectoryOwnership;
2+
use crate::module::DirOwnership;
33

44
use rustc_ast::ptr::P;
55
use rustc_ast::token::{self, Nonterminal};
66
use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, LazyTokenStream, TokenStream};
77
use rustc_ast::visit::{AssocCtxt, Visitor};
8-
use rustc_ast::{self as ast, AstLike, Attribute, NodeId, PatKind};
8+
use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind};
99
use rustc_attr::{self as attr, Deprecation, Stability};
1010
use rustc_data_structures::fx::FxHashMap;
1111
use rustc_data_structures::sync::{self, Lrc};
@@ -900,21 +900,40 @@ pub trait ResolverExpand {
900900
fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
901901
}
902902

903-
#[derive(Clone)]
903+
#[derive(Clone, Default)]
904904
pub struct ModuleData {
905+
/// Path to the module starting from the crate name, like `my_crate::foo::bar`.
905906
pub mod_path: Vec<Ident>,
906-
pub directory: PathBuf,
907+
/// Stack of paths to files loaded by out-of-line module items,
908+
/// used to detect and report recursive module inclusions.
909+
pub file_path_stack: Vec<PathBuf>,
910+
/// Directory to search child module files in,
911+
/// often (but not necessarily) the parent of the top file path on the `file_path_stack`.
912+
pub dir_path: PathBuf,
913+
}
914+
915+
impl ModuleData {
916+
pub fn with_dir_path(&self, dir_path: PathBuf) -> ModuleData {
917+
ModuleData {
918+
mod_path: self.mod_path.clone(),
919+
file_path_stack: self.file_path_stack.clone(),
920+
dir_path,
921+
}
922+
}
907923
}
908924

909925
#[derive(Clone)]
910926
pub struct ExpansionData {
911927
pub id: ExpnId,
912928
pub depth: usize,
913929
pub module: Rc<ModuleData>,
914-
pub directory_ownership: DirectoryOwnership,
930+
pub dir_ownership: DirOwnership,
915931
pub prior_type_ascription: Option<(Span, bool)>,
916932
}
917933

934+
type OnExternModLoaded<'a> =
935+
Option<&'a dyn Fn(Ident, Vec<Attribute>, Vec<P<Item>>, Span) -> (Vec<Attribute>, Vec<P<Item>>)>;
936+
918937
/// One of these is made during expansion and incrementally updated as we go;
919938
/// when a macro expansion occurs, the resulting nodes have the `backtrace()
920939
/// -> expn_data` of their expansion context stored into their span.
@@ -932,15 +951,15 @@ pub struct ExtCtxt<'a> {
932951
/// Called directly after having parsed an external `mod foo;` in expansion.
933952
///
934953
/// `Ident` is the module name.
935-
pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate, Ident)>,
954+
pub(super) extern_mod_loaded: OnExternModLoaded<'a>,
936955
}
937956

938957
impl<'a> ExtCtxt<'a> {
939958
pub fn new(
940959
sess: &'a Session,
941960
ecfg: expand::ExpansionConfig<'a>,
942961
resolver: &'a mut dyn ResolverExpand,
943-
extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate, Ident)>,
962+
extern_mod_loaded: OnExternModLoaded<'a>,
944963
) -> ExtCtxt<'a> {
945964
ExtCtxt {
946965
sess,
@@ -952,8 +971,8 @@ impl<'a> ExtCtxt<'a> {
952971
current_expansion: ExpansionData {
953972
id: ExpnId::root(),
954973
depth: 0,
955-
module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
956-
directory_ownership: DirectoryOwnership::Owned { relative: None },
974+
module: Default::default(),
975+
dir_ownership: DirOwnership::Owned { relative: None },
957976
prior_type_ascription: None,
958977
},
959978
force_mode: false,

compiler/rustc_expand/src/expand.rs

+65-49
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::config::StripUnconfigured;
33
use crate::configure;
44
use crate::hygiene::SyntaxContext;
55
use crate::mbe::macro_rules::annotate_err_with_kind;
6-
use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership};
6+
use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
77
use crate::placeholders::{placeholder, PlaceholderExpander};
88

99
use rustc_ast as ast;
@@ -355,16 +355,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
355355
// FIXME: Avoid visiting the crate as a `Mod` item,
356356
// make crate a first class expansion target instead.
357357
pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
358-
let mut module = ModuleData {
359-
mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
360-
directory: match self.cx.source_map().span_to_unmapped_path(krate.span) {
361-
FileName::Real(name) => name.into_local_path(),
362-
other => PathBuf::from(other.to_string()),
363-
},
358+
let file_path = match self.cx.source_map().span_to_unmapped_path(krate.span) {
359+
FileName::Real(name) => name.into_local_path(),
360+
other => PathBuf::from(other.to_string()),
364361
};
365-
module.directory.pop();
366-
self.cx.root_path = module.directory.clone();
367-
self.cx.current_expansion.module = Rc::new(module);
362+
let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
363+
self.cx.root_path = dir_path.clone();
364+
self.cx.current_expansion.module = Rc::new(ModuleData {
365+
mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
366+
file_path_stack: vec![file_path],
367+
dir_path,
368+
});
368369

369370
let krate_item = AstFragment::Items(smallvec![P(ast::Item {
370371
attrs: krate.attrs,
@@ -1245,10 +1246,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12451246
}
12461247

12471248
fn visit_block(&mut self, block: &mut P<Block>) {
1248-
let old_directory_ownership = self.cx.current_expansion.directory_ownership;
1249-
self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
1249+
let orig_dir_ownership = mem::replace(
1250+
&mut self.cx.current_expansion.dir_ownership,
1251+
DirOwnership::UnownedViaBlock,
1252+
);
12501253
noop_visit_block(block, self);
1251-
self.cx.current_expansion.directory_ownership = old_directory_ownership;
1254+
self.cx.current_expansion.dir_ownership = orig_dir_ownership;
12521255
}
12531256

12541257
fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
@@ -1276,63 +1279,76 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12761279
})
12771280
}
12781281
ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => {
1279-
let sess = &self.cx.sess.parse_sess;
1280-
let orig_ownership = self.cx.current_expansion.directory_ownership;
1281-
let mut module = (*self.cx.current_expansion.module).clone();
1282-
1283-
let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
1284-
let dir = Directory { ownership: orig_ownership, path: module.directory };
1285-
let Directory { ownership, path } = match mod_kind {
1286-
ModKind::Loaded(_, Inline::Yes, _) => {
1282+
let (file_path, dir_path, dir_ownership) = match mod_kind {
1283+
ModKind::Loaded(_, inline, _) => {
12871284
// Inline `mod foo { ... }`, but we still need to push directories.
1285+
assert!(
1286+
*inline == Inline::Yes,
1287+
"`mod` item is loaded from a file for the second time"
1288+
);
1289+
let (dir_path, dir_ownership) = mod_dir_path(
1290+
&self.cx.sess,
1291+
ident,
1292+
&attrs,
1293+
&self.cx.current_expansion.module,
1294+
self.cx.current_expansion.dir_ownership,
1295+
);
12881296
item.attrs = attrs;
1289-
push_directory(&self.cx.sess, ident, &item.attrs, dir)
1290-
}
1291-
ModKind::Loaded(_, Inline::No, _) => {
1292-
panic!("`mod` item is loaded from a file for the second time")
1297+
(None, dir_path, dir_ownership)
12931298
}
12941299
ModKind::Unloaded => {
12951300
// We have an outline `mod foo;` so we need to parse the file.
1296-
let (items, inner_span, dir) =
1297-
parse_external_mod(&self.cx.sess, ident, span, dir, &mut attrs, pushed);
1301+
let old_attrs_len = attrs.len();
1302+
let ParsedExternalMod {
1303+
mut items,
1304+
inner_span,
1305+
file_path,
1306+
dir_path,
1307+
dir_ownership,
1308+
} = parse_external_mod(
1309+
&self.cx.sess,
1310+
ident,
1311+
span,
1312+
&self.cx.current_expansion.module,
1313+
self.cx.current_expansion.dir_ownership,
1314+
&mut attrs,
1315+
);
12981316

1299-
let krate =
1300-
ast::Crate { attrs, items, span: inner_span, proc_macros: vec![] };
13011317
if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
1302-
extern_mod_loaded(&krate, ident);
1318+
(attrs, items) = extern_mod_loaded(ident, attrs, items, inner_span);
13031319
}
13041320

1305-
*mod_kind = ModKind::Loaded(krate.items, Inline::No, inner_span);
1306-
item.attrs = krate.attrs;
1307-
// File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1308-
item = match self.configure(item) {
1309-
Some(node) => node,
1310-
None => {
1311-
if *pushed {
1312-
sess.included_mod_stack.borrow_mut().pop();
1313-
}
1314-
return Default::default();
1315-
}
1316-
};
1317-
dir
1321+
*mod_kind = ModKind::Loaded(items, Inline::No, inner_span);
1322+
item.attrs = attrs;
1323+
if item.attrs.len() > old_attrs_len {
1324+
// If we loaded an out-of-line module and added some inner attributes,
1325+
// then we need to re-configure it.
1326+
// FIXME: Attributes also need to be recollected
1327+
// for resolution and expansion.
1328+
item = configure!(self, item);
1329+
}
1330+
(Some(file_path), dir_path, dir_ownership)
13181331
}
13191332
};
13201333

13211334
// Set the module info before we flat map.
1322-
self.cx.current_expansion.directory_ownership = ownership;
1323-
module.directory = path;
1335+
let mut module = self.cx.current_expansion.module.with_dir_path(dir_path);
13241336
module.mod_path.push(ident);
1337+
if let Some(file_path) = file_path {
1338+
module.file_path_stack.push(file_path);
1339+
}
1340+
13251341
let orig_module =
13261342
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
1343+
let orig_dir_ownership =
1344+
mem::replace(&mut self.cx.current_expansion.dir_ownership, dir_ownership);
13271345

13281346
let result = noop_flat_map_item(item, self);
13291347

13301348
// Restore the module info.
1349+
self.cx.current_expansion.dir_ownership = orig_dir_ownership;
13311350
self.cx.current_expansion.module = orig_module;
1332-
self.cx.current_expansion.directory_ownership = orig_ownership;
1333-
if *pushed {
1334-
sess.included_mod_stack.borrow_mut().pop();
1335-
}
1351+
13361352
result
13371353
}
13381354
_ => {

compiler/rustc_expand/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
#![feature(bool_to_option)]
12
#![feature(crate_visibility_modifier)]
23
#![feature(decl_macro)]
4+
#![feature(destructuring_assignment)]
35
#![feature(or_patterns)]
46
#![feature(proc_macro_diagnostic)]
57
#![feature(proc_macro_internals)]

0 commit comments

Comments
 (0)