Skip to content

Commit 9712711

Browse files
authored
Rollup merge of rust-lang#69838 - Centril:expand-module, r=petrochenkov
Expansion-driven outline module parsing After this PR, the parser will not do any conditional compilation or loading of external module files when `mod foo;` is encountered. Instead, the parser only leaves `mod foo;` in place in the AST, with no items filled in. Expansion later kicks in and will load the actual files and do the parsing. This entails that the following is now valid: ```rust #[cfg(FALSE)] mod foo { mod bar { mod baz; // `foo/bar/baz.rs` doesn't exist, but no error! } } ``` Fixes rust-lang#64197. r? @petrochenkov
2 parents fbf9590 + 8b0698b commit 9712711

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+599
-591
lines changed

src/libpanic_unwind/emcc.rs

-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
//! Emscripten's runtime always implements those APIs and does not
77
//! implement libunwind.
88
9-
#![allow(private_no_mangle_fns)]
10-
119
use alloc::boxed::Box;
1210
use core::any::Any;
1311
use core::mem;

src/libpanic_unwind/gcc.rs

-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636
//! Once stack has been unwound down to the handler frame level, unwinding stops
3737
//! and the last personality routine transfers control to the catch block.
3838
39-
#![allow(private_no_mangle_fns)]
40-
4139
use alloc::boxed::Box;
4240
use core::any::Any;
4341

src/libpanic_unwind/seh.rs

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
//! [llvm]: http://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions
4646
4747
#![allow(nonstandard_style)]
48-
#![allow(private_no_mangle_fns)]
4948

5049
use alloc::boxed::Box;
5150
use core::any::Any;

src/librustc_ast/ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2153,7 +2153,7 @@ impl FnRetTy {
21532153
/// Module declaration.
21542154
///
21552155
/// E.g., `mod foo;` or `mod foo { .. }`.
2156-
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2156+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
21572157
pub struct Mod {
21582158
/// A span from the first token past `{` to the last token until `}`.
21592159
/// For `mod foo;`, the inner span ranges from the first token

src/librustc_builtin_macros/proc_macro_harness.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub fn inject(
5959
handler: &rustc_errors::Handler,
6060
) -> ast::Crate {
6161
let ecfg = ExpansionConfig::default("proc_macro".to_string());
62-
let mut cx = ExtCtxt::new(sess, ecfg, resolver);
62+
let mut cx = ExtCtxt::new(sess, ecfg, resolver, None);
6363

6464
let mut collect = CollectProcMacros {
6565
macros: Vec::new(),

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_builtin_macros/standard_library_imports.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub fn inject(
3939
let call_site = DUMMY_SP.with_call_site_ctxt(expn_id);
4040

4141
let ecfg = ExpansionConfig::default("std_lib_injection".to_string());
42-
let cx = ExtCtxt::new(sess, ecfg, resolver);
42+
let cx = ExtCtxt::new(sess, ecfg, resolver, None);
4343

4444
// .rev() to preserve ordering above in combination with insert(0, ...)
4545
for &name in names.iter().rev() {

src/librustc_builtin_macros/test_harness.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ fn generate_test_harness(
202202
let mut econfig = ExpansionConfig::default("test".to_string());
203203
econfig.features = Some(features);
204204

205-
let ext_cx = ExtCtxt::new(sess, econfig, resolver);
205+
let ext_cx = ExtCtxt::new(sess, econfig, resolver, None);
206206

207207
let expn_id = ext_cx.resolver.expansion_for_ast_pass(
208208
DUMMY_SP,

src/librustc_expand/base.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::expand::{self, AstFragment, Invocation};
2+
use crate::module::DirectoryOwnership;
23

34
use rustc_ast::ast::{self, Attribute, Name, NodeId, PatKind};
45
use rustc_ast::mut_visit::{self, MutVisitor};
@@ -10,7 +11,7 @@ use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability};
1011
use rustc_data_structures::fx::FxHashMap;
1112
use rustc_data_structures::sync::{self, Lrc};
1213
use rustc_errors::{DiagnosticBuilder, DiagnosticId};
13-
use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS};
14+
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
1415
use rustc_session::parse::ParseSess;
1516
use rustc_span::edition::Edition;
1617
use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
@@ -925,19 +926,23 @@ pub struct ExtCtxt<'a> {
925926
pub resolver: &'a mut dyn Resolver,
926927
pub current_expansion: ExpansionData,
927928
pub expansions: FxHashMap<Span, Vec<String>>,
929+
/// Called directly after having parsed an external `mod foo;` in expansion.
930+
pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
928931
}
929932

930933
impl<'a> ExtCtxt<'a> {
931934
pub fn new(
932935
parse_sess: &'a ParseSess,
933936
ecfg: expand::ExpansionConfig<'a>,
934937
resolver: &'a mut dyn Resolver,
938+
extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
935939
) -> ExtCtxt<'a> {
936940
ExtCtxt {
937941
parse_sess,
938942
ecfg,
939-
root_path: PathBuf::new(),
940943
resolver,
944+
extern_mod_loaded,
945+
root_path: PathBuf::new(),
941946
current_expansion: ExpansionData {
942947
id: ExpnId::root(),
943948
depth: 0,

src/librustc_parse/config.rs src/librustc_expand/config.rs

+3-20
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
1-
//! Process the potential `cfg` attributes on a module.
2-
//! Also determine if the module should be included in this configuration.
3-
//!
4-
//! This module properly belongs in rustc_expand, but for now it's tied into
5-
//! parsing, so we leave it here to avoid complicated out-of-line dependencies.
6-
//!
7-
//! A principled solution to this wrong location would be to implement [#64197].
8-
//!
9-
//! [#64197]: https://github.com/rust-lang/rust/issues/64197
10-
11-
use crate::{parse_in, validate_attr};
1+
//! Conditional compilation stripping.
2+
123
use rustc_ast::ast::{self, AttrItem, Attribute, MetaItem};
134
use rustc_ast::attr::HasAttrs;
145
use rustc_ast::mut_visit::*;
@@ -21,6 +12,7 @@ use rustc_feature::{Feature, Features, State as FeatureState};
2112
use rustc_feature::{
2213
ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
2314
};
15+
use rustc_parse::{parse_in, validate_attr};
2416
use rustc_session::parse::{feature_err, ParseSess};
2517
use rustc_span::edition::{Edition, ALL_EDITIONS};
2618
use rustc_span::symbol::{sym, Symbol};
@@ -538,12 +530,3 @@ impl<'a> MutVisitor for StripUnconfigured<'a> {
538530
fn is_cfg(attr: &Attribute) -> bool {
539531
attr.check_name(sym::cfg)
540532
}
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_expand/expand.rs

+58-34
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use crate::base::*;
22
use crate::config::StripUnconfigured;
3+
use crate::configure;
34
use crate::hygiene::{ExpnData, ExpnId, ExpnKind, SyntaxContext};
45
use crate::mbe::macro_rules::annotate_err_with_kind;
6+
use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership};
57
use crate::placeholders::{placeholder, PlaceholderExpander};
68
use crate::proc_macro::collect_derives;
79

@@ -17,10 +19,8 @@ use rustc_ast_pretty::pprust;
1719
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
1820
use rustc_errors::{Applicability, FatalError, PResult};
1921
use rustc_feature::Features;
20-
use rustc_parse::configure;
2122
use rustc_parse::parser::Parser;
2223
use rustc_parse::validate_attr;
23-
use rustc_parse::DirectoryOwnership;
2424
use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
2525
use rustc_session::lint::BuiltinLintDiagnostics;
2626
use rustc_session::parse::{feature_err, ParseSess};
@@ -1427,59 +1427,83 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14271427
.make_items();
14281428
}
14291429

1430+
let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck.
1431+
let ident = item.ident;
1432+
let span = item.span;
1433+
14301434
match item.kind {
14311435
ast::ItemKind::MacCall(..) => {
1436+
item.attrs = attrs;
14321437
self.check_attributes(&item.attrs);
14331438
item.and_then(|item| match item.kind {
14341439
ItemKind::MacCall(mac) => self
1435-
.collect(
1436-
AstFragmentKind::Items,
1437-
InvocationKind::Bang { mac, span: item.span },
1438-
)
1440+
.collect(AstFragmentKind::Items, InvocationKind::Bang { mac, span })
14391441
.make_items(),
14401442
_ => unreachable!(),
14411443
})
14421444
}
1443-
ast::ItemKind::Mod(ast::Mod { inner, inline, .. })
1444-
if item.ident != Ident::invalid() =>
1445-
{
1446-
let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
1445+
ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => {
1446+
let sess = self.cx.parse_sess;
1447+
let orig_ownership = self.cx.current_expansion.directory_ownership;
14471448
let mut module = (*self.cx.current_expansion.module).clone();
1448-
module.mod_path.push(item.ident);
14491449

1450-
if inline {
1451-
if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) {
1452-
self.cx.current_expansion.directory_ownership =
1453-
DirectoryOwnership::Owned { relative: None };
1454-
module.directory.push(&*path.as_str());
1455-
} else {
1456-
module.directory.push(&*item.ident.as_str());
1457-
}
1450+
let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
1451+
let dir = Directory { ownership: orig_ownership, path: module.directory };
1452+
let Directory { ownership, path } = if old_mod.inline {
1453+
// Inline `mod foo { ... }`, but we still need to push directories.
1454+
item.attrs = attrs;
1455+
push_directory(ident, &item.attrs, dir)
14581456
} 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()),
1457+
// We have an outline `mod foo;` so we need to parse the file.
1458+
let (new_mod, dir) =
1459+
parse_external_mod(sess, ident, span, dir, &mut attrs, pushed);
1460+
1461+
let krate = ast::Crate {
1462+
span: new_mod.inner,
1463+
module: new_mod,
1464+
attrs,
1465+
proc_macros: vec![],
14631466
};
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,
1467+
if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
1468+
extern_mod_loaded(&krate);
1469+
}
1470+
1471+
*old_mod = krate.module;
1472+
item.attrs = krate.attrs;
1473+
// File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1474+
item = match self.configure(item) {
1475+
Some(node) => node,
1476+
None => {
1477+
if *pushed {
1478+
sess.included_mod_stack.borrow_mut().pop();
1479+
}
1480+
return Default::default();
1481+
}
14681482
};
1469-
path.pop();
1470-
module.directory = path;
1471-
self.cx.current_expansion.directory_ownership = directory_ownership;
1472-
}
1483+
dir
1484+
};
14731485

1486+
// Set the module info before we flat map.
1487+
self.cx.current_expansion.directory_ownership = ownership;
1488+
module.directory = path;
1489+
module.mod_path.push(ident);
14741490
let orig_module =
14751491
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
1492+
14761493
let result = noop_flat_map_item(item, self);
1494+
1495+
// Restore the module info.
14771496
self.cx.current_expansion.module = orig_module;
1478-
self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1497+
self.cx.current_expansion.directory_ownership = orig_ownership;
1498+
if *pushed {
1499+
sess.included_mod_stack.borrow_mut().pop();
1500+
}
14791501
result
14801502
}
1481-
1482-
_ => noop_flat_map_item(item, self),
1503+
_ => {
1504+
item.attrs = attrs;
1505+
noop_flat_map_item(item, self)
1506+
}
14831507
}
14841508
}
14851509

src/librustc_expand/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
#![feature(bool_to_option)]
12
#![feature(cow_is_borrowed)]
23
#![feature(crate_visibility_modifier)]
34
#![feature(decl_macro)]
45
#![feature(proc_macro_diagnostic)]
56
#![feature(proc_macro_internals)]
67
#![feature(proc_macro_span)]
8+
#![feature(try_blocks)]
79

810
extern crate proc_macro as pm;
911

@@ -33,8 +35,10 @@ pub use mbe::macro_rules::compile_declarative_macro;
3335
crate use rustc_span::hygiene;
3436
pub mod base;
3537
pub mod build;
38+
#[macro_use]
39+
pub mod config;
3640
pub mod expand;
37-
pub use rustc_parse::config;
41+
pub mod module;
3842
pub mod proc_macro;
3943

4044
crate mod mbe;

0 commit comments

Comments
 (0)