Skip to content

Commit 83a757a

Browse files
committed
outline modules: parse -> expand.
1 parent 59bf8a0 commit 83a757a

File tree

8 files changed

+116
-180
lines changed

8 files changed

+116
-180
lines changed

src/librustc_builtin_macros/source_util.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_ast::tokenstream::TokenStream;
55
use rustc_ast_pretty::pprust;
66
use rustc_expand::base::{self, *};
77
use rustc_expand::panictry;
8-
use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership};
8+
use rustc_parse::{self, new_sub_parser_from_file, parser::Parser};
99
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
1010
use rustc_span::symbol::Symbol;
1111
use rustc_span::{self, Pos, Span};
@@ -108,8 +108,7 @@ pub fn expand_include<'cx>(
108108
return DummyResult::any(sp);
109109
}
110110
};
111-
let directory_ownership = DirectoryOwnership::Owned { relative: None };
112-
let p = new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp);
111+
let p = new_sub_parser_from_file(cx.parse_sess(), &file, None, sp);
113112

114113
struct ExpandResult<'a> {
115114
p: Parser<'a>,

src/librustc_expand/expand.rs

+46-31
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
1818
use rustc_errors::{Applicability, FatalError, PResult};
1919
use rustc_feature::Features;
2020
use rustc_parse::configure;
21-
use rustc_parse::parser::module;
21+
use rustc_parse::parser::module::{parse_external_mod, push_directory};
2222
use rustc_parse::parser::Parser;
2323
use rustc_parse::validate_attr;
24-
use rustc_parse::DirectoryOwnership;
24+
use rustc_parse::{Directory, DirectoryOwnership};
2525
use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
2626
use rustc_session::lint::BuiltinLintDiagnostics;
2727
use rustc_session::parse::{feature_err, ParseSess};
@@ -1428,8 +1428,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14281428
.make_items();
14291429
}
14301430

1431+
let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck.
1432+
let ident = item.ident;
1433+
14311434
match item.kind {
14321435
ast::ItemKind::MacCall(..) => {
1436+
item.attrs = attrs;
14331437
self.check_attributes(&item.attrs);
14341438
item.and_then(|item| match item.kind {
14351439
ItemKind::MacCall(mac) => self
@@ -1441,45 +1445,56 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14411445
_ => unreachable!(),
14421446
})
14431447
}
1444-
ast::ItemKind::Mod(ast::Mod { inner, inline, .. })
1445-
if item.ident != Ident::invalid() =>
1446-
{
1447-
let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
1448+
ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => {
1449+
let sess = self.cx.parse_sess;
1450+
let orig_ownership = self.cx.current_expansion.directory_ownership;
14481451
let mut module = (*self.cx.current_expansion.module).clone();
1449-
module.mod_path.push(item.ident);
1450-
1451-
if inline {
1452-
module::push_directory(
1453-
item.ident,
1454-
&item.attrs,
1455-
&mut self.cx.current_expansion.directory_ownership,
1456-
&mut module.directory,
1457-
);
1452+
1453+
let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
1454+
let dir = Directory { ownership: orig_ownership, path: module.directory };
1455+
let Directory { ownership, path } = if old_mod.inline {
1456+
// Inline `mod foo { ... }`, but we still need to push directories.
1457+
item.attrs = attrs;
1458+
push_directory(ident, &item.attrs, dir)
14581459
} else {
1459-
let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner);
1460-
let mut path = match path {
1461-
FileName::Real(path) => path,
1462-
other => PathBuf::from(other.to_string()),
1463-
};
1464-
let directory_ownership = match path.file_name().unwrap().to_str() {
1465-
Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
1466-
Some(_) => DirectoryOwnership::Owned { relative: Some(item.ident) },
1467-
None => DirectoryOwnership::UnownedViaMod,
1460+
// We have an outline `mod foo;` so we need to parse the file.
1461+
let (new_mod, dir) = parse_external_mod(sess, ident, dir, &mut attrs, pushed);
1462+
*old_mod = new_mod;
1463+
item.attrs = attrs;
1464+
// File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1465+
item = match self.configure(item) {
1466+
Some(node) => node,
1467+
None => {
1468+
if *pushed {
1469+
sess.included_mod_stack.borrow_mut().pop();
1470+
}
1471+
return Default::default();
1472+
}
14681473
};
1469-
path.pop();
1470-
module.directory = path;
1471-
self.cx.current_expansion.directory_ownership = directory_ownership;
1472-
}
1474+
dir
1475+
};
14731476

1477+
// Set the module info before we flat map.
1478+
self.cx.current_expansion.directory_ownership = ownership;
1479+
module.directory = path;
1480+
module.mod_path.push(ident);
14741481
let orig_module =
14751482
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
1483+
14761484
let result = noop_flat_map_item(item, self);
1485+
1486+
// Restore the module info.
14771487
self.cx.current_expansion.module = orig_module;
1478-
self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1488+
self.cx.current_expansion.directory_ownership = orig_ownership;
1489+
if *pushed {
1490+
sess.included_mod_stack.borrow_mut().pop();
1491+
}
14791492
result
14801493
}
1481-
1482-
_ => noop_flat_map_item(item, self),
1494+
_ => {
1495+
item.attrs = attrs;
1496+
noop_flat_map_item(item, self)
1497+
}
14831498
}
14841499
}
14851500

src/librustc_expand/mbe/macro_rules.rs

+12-25
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::base::{DummyResult, ExpansionData, ExtCtxt, MacResult, TTMacroExpander};
1+
use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
22
use crate::base::{SyntaxExtension, SyntaxExtensionKind};
33
use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind};
44
use crate::mbe;
@@ -18,7 +18,6 @@ use rustc_data_structures::sync::Lrc;
1818
use rustc_errors::{Applicability, DiagnosticBuilder, FatalError};
1919
use rustc_feature::Features;
2020
use rustc_parse::parser::Parser;
21-
use rustc_parse::Directory;
2221
use rustc_session::parse::ParseSess;
2322
use rustc_span::edition::Edition;
2423
use rustc_span::hygiene::Transparency;
@@ -182,6 +181,8 @@ fn generic_extension<'cx>(
182181
lhses: &[mbe::TokenTree],
183182
rhses: &[mbe::TokenTree],
184183
) -> Box<dyn MacResult + 'cx> {
184+
let sess = cx.parse_sess;
185+
185186
if cx.trace_macros() {
186187
let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone()));
187188
trace_macros_note(&mut cx.expansions, sp, msg);
@@ -209,7 +210,7 @@ fn generic_extension<'cx>(
209210
// hacky, but speeds up the `html5ever` benchmark significantly. (Issue
210211
// 68836 suggests a more comprehensive but more complex change to deal with
211212
// this situation.)
212-
let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone());
213+
let parser = parser_from_cx(sess, arg.clone());
213214

214215
for (i, lhs) in lhses.iter().enumerate() {
215216
// try each arm's matchers
@@ -222,14 +223,13 @@ fn generic_extension<'cx>(
222223
// This is used so that if a matcher is not `Success(..)`ful,
223224
// then the spans which became gated when parsing the unsuccessful matcher
224225
// are not recorded. On the first `Success(..)`ful matcher, the spans are merged.
225-
let mut gated_spans_snapshot =
226-
mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut());
226+
let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut());
227227

228228
match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) {
229229
Success(named_matches) => {
230230
// The matcher was `Success(..)`ful.
231231
// Merge the gated spans from parsing the matcher with the pre-existing ones.
232-
cx.parse_sess.gated_spans.merge(gated_spans_snapshot);
232+
sess.gated_spans.merge(gated_spans_snapshot);
233233

234234
let rhs = match rhses[i] {
235235
// ignore delimiters
@@ -258,11 +258,7 @@ fn generic_extension<'cx>(
258258
trace_macros_note(&mut cx.expansions, sp, msg);
259259
}
260260

261-
let directory = Directory {
262-
path: cx.current_expansion.module.directory.clone(),
263-
ownership: cx.current_expansion.directory_ownership,
264-
};
265-
let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None);
261+
let mut p = Parser::new(cx.parse_sess(), tts, false, None);
266262
p.root_module_name =
267263
cx.current_expansion.module.mod_path.last().map(|id| id.to_string());
268264
p.last_type_ascription = cx.current_expansion.prior_type_ascription;
@@ -289,7 +285,7 @@ fn generic_extension<'cx>(
289285

290286
// The matcher was not `Success(..)`ful.
291287
// Restore to the state before snapshotting and maybe try again.
292-
mem::swap(&mut gated_spans_snapshot, &mut cx.parse_sess.gated_spans.spans.borrow_mut());
288+
mem::swap(&mut gated_spans_snapshot, &mut sess.gated_spans.spans.borrow_mut());
293289
}
294290
drop(parser);
295291

@@ -309,8 +305,7 @@ fn generic_extension<'cx>(
309305
mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..],
310306
_ => continue,
311307
};
312-
let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone());
313-
match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) {
308+
match parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt) {
314309
Success(_) => {
315310
if comma_span.is_dummy() {
316311
err.note("you might be missing a comma");
@@ -392,7 +387,7 @@ pub fn compile_declarative_macro(
392387
),
393388
];
394389

395-
let parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS);
390+
let parser = Parser::new(sess, body, true, rustc_parse::MACRO_ARGUMENTS);
396391
let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) {
397392
Success(m) => m,
398393
Failure(token, msg) => {
@@ -1209,16 +1204,8 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
12091204
}
12101205
}
12111206

1212-
fn parser_from_cx<'cx>(
1213-
current_expansion: &'cx ExpansionData,
1214-
sess: &'cx ParseSess,
1215-
tts: TokenStream,
1216-
) -> Parser<'cx> {
1217-
let directory = Directory {
1218-
path: current_expansion.module.directory.clone(),
1219-
ownership: current_expansion.directory_ownership,
1220-
};
1221-
Parser::new(sess, tts, Some(directory), true, true, rustc_parse::MACRO_ARGUMENTS)
1207+
fn parser_from_cx<'cx>(sess: &'cx ParseSess, tts: TokenStream) -> Parser<'cx> {
1208+
Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS)
12221209
}
12231210

12241211
/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For

src/librustc_parse/config.rs

-9
Original file line numberDiff line numberDiff line change
@@ -538,12 +538,3 @@ impl<'a> MutVisitor for StripUnconfigured<'a> {
538538
fn is_cfg(attr: &Attribute) -> bool {
539539
attr.check_name(sym::cfg)
540540
}
541-
542-
/// Process the potential `cfg` attributes on a module.
543-
/// Also determine if the module should be included in this configuration.
544-
pub fn process_configure_mod(sess: &ParseSess, cfg_mods: bool, attrs: &mut Vec<Attribute>) -> bool {
545-
// Don't perform gated feature checking.
546-
let mut strip_unconfigured = StripUnconfigured { sess, features: None };
547-
strip_unconfigured.process_cfg_attrs(attrs);
548-
!cfg_mods || strip_unconfigured.in_cfg(&attrs)
549-
}

src/librustc_parse/lib.rs

+6-14
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![feature(bool_to_option)]
44
#![feature(crate_visibility_modifier)]
55
#![feature(bindings_after_at)]
6+
#![feature(try_blocks)]
67

78
use rustc_ast::ast;
89
use rustc_ast::token::{self, Nonterminal};
@@ -119,10 +120,7 @@ pub fn maybe_new_parser_from_source_str(
119120
name: FileName,
120121
source: String,
121122
) -> Result<Parser<'_>, Vec<Diagnostic>> {
122-
let mut parser =
123-
maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))?;
124-
parser.recurse_into_file_modules = false;
125-
Ok(parser)
123+
maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))
126124
}
127125

128126
/// Creates a new parser, handling errors as appropriate if the file doesn't exist.
@@ -146,12 +144,10 @@ pub fn maybe_new_parser_from_file<'a>(
146144
pub fn new_sub_parser_from_file<'a>(
147145
sess: &'a ParseSess,
148146
path: &Path,
149-
directory_ownership: DirectoryOwnership,
150147
module_name: Option<String>,
151148
sp: Span,
152149
) -> Parser<'a> {
153150
let mut p = source_file_to_parser(sess, file_to_source_file(sess, path, Some(sp)));
154-
p.directory.ownership = directory_ownership;
155151
p.root_module_name = module_name;
156152
p
157153
}
@@ -257,7 +253,7 @@ pub fn stream_to_parser<'a>(
257253
stream: TokenStream,
258254
subparser_name: Option<&'static str>,
259255
) -> Parser<'a> {
260-
Parser::new(sess, stream, None, true, false, subparser_name)
256+
Parser::new(sess, stream, false, subparser_name)
261257
}
262258

263259
/// Given a stream, the `ParseSess` and the base directory, produces a parser.
@@ -271,12 +267,8 @@ pub fn stream_to_parser<'a>(
271267
/// The main usage of this function is outside of rustc, for those who uses
272268
/// librustc_ast as a library. Please do not remove this function while refactoring
273269
/// just because it is not used in rustc codebase!
274-
pub fn stream_to_parser_with_base_dir(
275-
sess: &ParseSess,
276-
stream: TokenStream,
277-
base_dir: Directory,
278-
) -> Parser<'_> {
279-
Parser::new(sess, stream, Some(base_dir), true, false, None)
270+
pub fn stream_to_parser_with_base_dir(sess: &ParseSess, stream: TokenStream) -> Parser<'_> {
271+
Parser::new(sess, stream, false, None)
280272
}
281273

282274
/// Runs the given subparser `f` on the tokens of the given `attr`'s item.
@@ -286,7 +278,7 @@ pub fn parse_in<'a, T>(
286278
name: &'static str,
287279
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
288280
) -> PResult<'a, T> {
289-
let mut parser = Parser::new(sess, tts, None, false, false, Some(name));
281+
let mut parser = Parser::new(sess, tts, false, Some(name));
290282
let result = f(&mut parser)?;
291283
if parser.token != token::Eof {
292284
parser.unexpected()?;

0 commit comments

Comments
 (0)