Skip to content

Commit 4a88165

Browse files
committed
ast: Keep expansion status for out-of-line module items
Also remove `ast::Mod` which is mostly redundant now
1 parent eb65f15 commit 4a88165

File tree

14 files changed

+147
-125
lines changed

14 files changed

+147
-125
lines changed

Diff for: compiler/rustc_ast/src/ast.rs

+18-15
Original file line numberDiff line numberDiff line change
@@ -2299,21 +2299,22 @@ impl FnRetTy {
22992299
}
23002300
}
23012301

2302-
/// Module declaration.
2303-
///
2304-
/// E.g., `mod foo;` or `mod foo { .. }`.
2302+
#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
2303+
pub enum Inline {
2304+
Yes,
2305+
No,
2306+
}
2307+
2308+
/// Module item kind.
23052309
#[derive(Clone, Encodable, Decodable, Debug)]
2306-
pub struct Mod {
2307-
/// A span from the first token past `{` to the last token until `}`.
2308-
/// For `mod foo;`, the inner span ranges from the first token
2309-
/// to the last token in the external file.
2310-
pub inner: Span,
2311-
/// `unsafe` keyword accepted syntactically for macro DSLs, but not
2312-
/// semantically by Rust.
2313-
pub unsafety: Unsafe,
2314-
pub items: Vec<P<Item>>,
2315-
/// `true` for `mod foo { .. }`; `false` for `mod foo;`.
2316-
pub inline: bool,
2310+
pub enum ModKind {
2311+
/// Module with inlined definition `mod foo { ... }`,
2312+
/// or with definition outlined to a separate file `mod foo;` and already loaded from it.
2313+
/// The inner span is from the first token past `{` to the last token until `}`,
2314+
/// or from the first to the last token in the loaded file.
2315+
Loaded(Vec<P<Item>>, Inline, Span),
2316+
/// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it.
2317+
Unloaded,
23172318
}
23182319

23192320
/// Foreign module declaration.
@@ -2710,7 +2711,9 @@ pub enum ItemKind {
27102711
/// A module declaration (`mod`).
27112712
///
27122713
/// E.g., `mod foo;` or `mod foo { .. }`.
2713-
Mod(Mod),
2714+
/// `unsafe` keyword on modules is accepted syntactically for macro DSLs, but not
2715+
/// semantically by Rust.
2716+
Mod(Unsafe, ModKind),
27142717
/// An external module (`extern`).
27152718
///
27162719
/// E.g., `extern {}` or `extern "C" {}`.

Diff for: compiler/rustc_ast/src/mut_visit.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -913,11 +913,13 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
913913
vis.visit_generics(generics);
914914
visit_opt(body, |body| vis.visit_block(body));
915915
}
916-
ItemKind::Mod(m) => {
917-
let Mod { inner, unsafety: _, items, inline: _ } = m;
918-
vis.visit_span(inner);
919-
items.flat_map_in_place(|item| vis.flat_map_item(item));
920-
}
916+
ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
917+
ModKind::Loaded(items, _inline, inner_span) => {
918+
vis.visit_span(inner_span);
919+
items.flat_map_in_place(|item| vis.flat_map_item(item));
920+
}
921+
ModKind::Unloaded => {}
922+
},
921923
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
922924
ItemKind::GlobalAsm(_ga) => {}
923925
ItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
@@ -1010,7 +1012,7 @@ pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
10101012
id: DUMMY_NODE_ID,
10111013
vis: item_vis,
10121014
span,
1013-
kind: ItemKind::Mod(Mod { inner: span, unsafety: Unsafe::No, items, inline: true }),
1015+
kind: ItemKind::Mod(Unsafe::No, ModKind::Loaded(items, Inline::Yes, span)),
10141016
tokens: None,
10151017
});
10161018
let items = vis.flat_map_item(item);
@@ -1021,7 +1023,9 @@ pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
10211023
} else if len == 1 {
10221024
let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner();
10231025
match kind {
1024-
ItemKind::Mod(module) => Crate { attrs, items: module.items, span, proc_macros },
1026+
ItemKind::Mod(_, ModKind::Loaded(items, ..)) => {
1027+
Crate { attrs, items, span, proc_macros }
1028+
}
10251029
_ => panic!("visitor converted a module to not a module"),
10261030
}
10271031
} else {

Diff for: compiler/rustc_ast/src/visit.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
290290
let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
291291
visitor.visit_fn(kind, item.span, item.id)
292292
}
293-
ItemKind::Mod(ref module) => walk_list!(visitor, visit_item, &module.items),
293+
ItemKind::Mod(_unsafety, ref mod_kind) => match mod_kind {
294+
ModKind::Loaded(items, _inline, _inner_span) => {
295+
walk_list!(visitor, visit_item, items)
296+
}
297+
ModKind::Unloaded => {}
298+
},
294299
ItemKind::ForeignMod(ref foreign_module) => {
295300
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
296301
}

Diff for: compiler/rustc_ast_lowering/src/item.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
314314
hir::ItemKind::Fn(sig, generics, body_id)
315315
})
316316
}
317-
ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(&m.items, m.inner)),
317+
ItemKind::Mod(_, ref mod_kind) => match mod_kind {
318+
ModKind::Loaded(items, _, inner_span) => {
319+
hir::ItemKind::Mod(self.lower_mod(items, *inner_span))
320+
}
321+
ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
322+
},
318323
ItemKind::ForeignMod(ref fm) => {
319324
if fm.abi.is_none() {
320325
self.maybe_lint_missing_abi(span, id, abi::Abi::C);

Diff for: compiler/rustc_ast_passes/src/ast_validation.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1054,12 +1054,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10541054
walk_list!(self, visit_attribute, &item.attrs);
10551055
return;
10561056
}
1057-
ItemKind::Mod(Mod { inline, unsafety, .. }) => {
1057+
ItemKind::Mod(unsafety, ref mod_kind) => {
10581058
if let Unsafe::Yes(span) = unsafety {
10591059
self.err_handler().span_err(span, "module cannot be declared unsafe");
10601060
}
10611061
// Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
1062-
if !inline && !self.session.contains_name(&item.attrs, sym::path) {
1062+
if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _))
1063+
&& !self.session.contains_name(&item.attrs, sym::path)
1064+
{
10631065
self.check_mod_file_item_asciionly(item.ident);
10641066
}
10651067
}

Diff for: compiler/rustc_ast_pretty/src/pprust/state.rs

+20-22
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_ast::util::classify;
99
use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
1010
use rustc_ast::util::parser::{self, AssocOp, Fixity};
1111
use rustc_ast::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
12-
use rustc_ast::{GenericArg, MacArgs};
12+
use rustc_ast::{GenericArg, MacArgs, ModKind};
1313
use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier};
1414
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
1515
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
@@ -87,7 +87,6 @@ pub struct State<'a> {
8787
pub s: pp::Printer,
8888
comments: Option<Comments<'a>>,
8989
ann: &'a (dyn PpAnn + 'a),
90-
is_expanded: bool,
9190
}
9291

9392
crate const INDENT_UNIT: usize = 4;
@@ -103,12 +102,8 @@ pub fn print_crate<'a>(
103102
is_expanded: bool,
104103
edition: Edition,
105104
) -> String {
106-
let mut s = State {
107-
s: pp::mk_printer(),
108-
comments: Some(Comments::new(sm, filename, input)),
109-
ann,
110-
is_expanded,
111-
};
105+
let mut s =
106+
State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann };
112107

113108
if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
114109
// We need to print `#![no_std]` (and its feature gate) so that
@@ -856,7 +851,7 @@ impl<'a> PrintState<'a> for State<'a> {
856851

857852
impl<'a> State<'a> {
858853
pub fn new() -> State<'a> {
859-
State { s: pp::mk_printer(), comments: None, ann: &NoAnn, is_expanded: false }
854+
State { s: pp::mk_printer(), comments: None, ann: &NoAnn }
860855
}
861856

862857
// Synthesizes a comment that was not textually present in the original source
@@ -1134,26 +1129,29 @@ impl<'a> State<'a> {
11341129
let body = body.as_deref();
11351130
self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs);
11361131
}
1137-
ast::ItemKind::Mod(ref _mod) => {
1132+
ast::ItemKind::Mod(unsafety, ref mod_kind) => {
11381133
self.head(self.to_string(|s| {
11391134
s.print_visibility(&item.vis);
1140-
s.print_unsafety(_mod.unsafety);
1135+
s.print_unsafety(unsafety);
11411136
s.word("mod");
11421137
}));
11431138
self.print_ident(item.ident);
11441139

1145-
if _mod.inline || self.is_expanded {
1146-
self.nbsp();
1147-
self.bopen();
1148-
self.print_inner_attributes(&item.attrs);
1149-
for item in &_mod.items {
1150-
self.print_item(item);
1140+
match mod_kind {
1141+
ModKind::Loaded(items, ..) => {
1142+
self.nbsp();
1143+
self.bopen();
1144+
self.print_inner_attributes(&item.attrs);
1145+
for item in items {
1146+
self.print_item(item);
1147+
}
1148+
self.bclose(item.span);
1149+
}
1150+
ModKind::Unloaded => {
1151+
self.s.word(";");
1152+
self.end(); // end inner head-block
1153+
self.end(); // end outer head-block
11511154
}
1152-
self.bclose(item.span);
1153-
} else {
1154-
self.s.word(";");
1155-
self.end(); // end inner head-block
1156-
self.end(); // end outer head-block
11571155
}
11581156
}
11591157
ast::ItemKind::ForeignMod(ref nmod) => {

Diff for: compiler/rustc_builtin_macros/src/test_harness.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// Code that generates a test runner to run all the tests in a crate
22

33
use rustc_ast as ast;
4-
use rustc_ast::attr;
54
use rustc_ast::entry::EntryPointType;
65
use rustc_ast::mut_visit::{ExpectOne, *};
76
use rustc_ast::ptr::P;
7+
use rustc_ast::{attr, ModKind};
88
use rustc_expand::base::{ExtCtxt, ResolverExpand};
99
use rustc_expand::expand::{AstFragment, ExpansionConfig};
1010
use rustc_feature::Features;
@@ -106,19 +106,19 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
106106
if let ast::ItemKind::Mod(..) = item.kind {
107107
let tests = mem::take(&mut self.tests);
108108
noop_visit_item_kind(&mut item.kind, self);
109-
let module = match item.kind {
110-
ast::ItemKind::Mod(module) => module,
111-
_ => unreachable!(),
112-
};
113109
let mut tests = mem::replace(&mut self.tests, tests);
114110

115111
if !tests.is_empty() {
116112
let parent =
117113
if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id };
118114
// Create an identifier that will hygienically resolve the test
119115
// case name, even in another module.
116+
let inner_span = match item.kind {
117+
ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) => span,
118+
_ => unreachable!(),
119+
};
120120
let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
121-
module.inner,
121+
inner_span,
122122
AstPass::TestHarness,
123123
&[],
124124
Some(parent),
@@ -130,7 +130,6 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
130130
}
131131
self.cx.test_cases.extend(tests);
132132
}
133-
item.kind = ast::ItemKind::Mod(module);
134133
}
135134
smallvec![P(item)]
136135
}

Diff for: compiler/rustc_expand/src/expand.rs

+47-43
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use rustc_ast::ptr::P;
1212
use rustc_ast::token;
1313
use rustc_ast::tokenstream::TokenStream;
1414
use rustc_ast::visit::{self, AssocCtxt, Visitor};
15-
use rustc_ast::{AttrItem, AttrStyle, Block, ItemKind, LitKind, MacArgs};
16-
use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, NestedMetaItem};
15+
use rustc_ast::{AttrItem, AttrStyle, Block, Inline, ItemKind, LitKind, MacArgs};
16+
use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
1717
use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
1818
use rustc_ast_pretty::pprust;
1919
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
@@ -367,12 +367,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
367367
let krate_item = AstFragment::Items(smallvec![P(ast::Item {
368368
attrs: krate.attrs,
369369
span: krate.span,
370-
kind: ast::ItemKind::Mod(ast::Mod {
371-
inner: krate.span,
372-
unsafety: Unsafe::No,
373-
items: krate.items,
374-
inline: true
375-
}),
370+
kind: ast::ItemKind::Mod(
371+
Unsafe::No,
372+
ModKind::Loaded(krate.items, Inline::Yes, krate.span)
373+
),
376374
ident: Ident::invalid(),
377375
id: ast::DUMMY_NODE_ID,
378376
vis: ast::Visibility {
@@ -384,9 +382,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
384382
})]);
385383

386384
match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
387-
Some(ast::Item { attrs, kind: ast::ItemKind::Mod(module), .. }) => {
385+
Some(ast::Item {
386+
attrs,
387+
kind: ast::ItemKind::Mod(_, ModKind::Loaded(items, ..)),
388+
..
389+
}) => {
388390
krate.attrs = attrs;
389-
krate.items = module.items;
391+
krate.items = items;
390392
}
391393
None => {
392394
// Resolution failed so we return an empty expansion
@@ -809,7 +811,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
809811
impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
810812
fn visit_item(&mut self, item: &'ast ast::Item) {
811813
match &item.kind {
812-
ast::ItemKind::Mod(module) if !module.inline => {
814+
ast::ItemKind::Mod(_, mod_kind)
815+
if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
816+
{
813817
feature_err(
814818
self.parse_sess,
815819
sym::proc_macro_hygiene,
@@ -1266,47 +1270,47 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12661270
_ => unreachable!(),
12671271
})
12681272
}
1269-
ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => {
1273+
ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => {
12701274
let sess = &self.cx.sess.parse_sess;
12711275
let orig_ownership = self.cx.current_expansion.directory_ownership;
12721276
let mut module = (*self.cx.current_expansion.module).clone();
12731277

12741278
let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
12751279
let dir = Directory { ownership: orig_ownership, path: module.directory };
1276-
let Directory { ownership, path } = if old_mod.inline {
1277-
// Inline `mod foo { ... }`, but we still need to push directories.
1278-
item.attrs = attrs;
1279-
push_directory(&self.cx.sess, ident, &item.attrs, dir)
1280-
} else {
1281-
// We have an outline `mod foo;` so we need to parse the file.
1282-
let (ast::Mod { unsafety, inline, items, inner }, dir) = parse_external_mod(
1283-
&self.cx.sess,
1284-
ident,
1285-
span,
1286-
old_mod.unsafety,
1287-
dir,
1288-
&mut attrs,
1289-
pushed,
1290-
);
1291-
1292-
let krate = ast::Crate { attrs, items, span: inner, proc_macros: vec![] };
1293-
if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
1294-
extern_mod_loaded(&krate, ident);
1280+
let Directory { ownership, path } = match mod_kind {
1281+
ModKind::Loaded(_, Inline::Yes, _) => {
1282+
// Inline `mod foo { ... }`, but we still need to push directories.
1283+
item.attrs = attrs;
1284+
push_directory(&self.cx.sess, ident, &item.attrs, dir)
1285+
}
1286+
ModKind::Loaded(_, Inline::No, _) => {
1287+
panic!("`mod` item is loaded from a file for the second time")
12951288
}
1289+
ModKind::Unloaded => {
1290+
// We have an outline `mod foo;` so we need to parse the file.
1291+
let (items, inner_span, dir) =
1292+
parse_external_mod(&self.cx.sess, ident, span, dir, &mut attrs, pushed);
1293+
1294+
let krate =
1295+
ast::Crate { attrs, items, span: inner_span, proc_macros: vec![] };
1296+
if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
1297+
extern_mod_loaded(&krate, ident);
1298+
}
12961299

1297-
*old_mod = ast::Mod { unsafety, inline, items: krate.items, inner };
1298-
item.attrs = krate.attrs;
1299-
// File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1300-
item = match self.configure(item) {
1301-
Some(node) => node,
1302-
None => {
1303-
if *pushed {
1304-
sess.included_mod_stack.borrow_mut().pop();
1300+
*mod_kind = ModKind::Loaded(krate.items, Inline::No, inner_span);
1301+
item.attrs = krate.attrs;
1302+
// File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1303+
item = match self.configure(item) {
1304+
Some(node) => node,
1305+
None => {
1306+
if *pushed {
1307+
sess.included_mod_stack.borrow_mut().pop();
1308+
}
1309+
return Default::default();
13051310
}
1306-
return Default::default();
1307-
}
1308-
};
1309-
dir
1311+
};
1312+
dir
1313+
}
13101314
};
13111315

13121316
// Set the module info before we flat map.

0 commit comments

Comments
 (0)