Skip to content

Commit b158edc

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 9b26188 + 5cc4e94 commit b158edc

Some content is hidden

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

45 files changed

+587
-587
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};
@@ -922,19 +923,23 @@ pub struct ExtCtxt<'a> {
922923
pub resolver: &'a mut dyn Resolver,
923924
pub current_expansion: ExpansionData,
924925
pub expansions: FxHashMap<Span, Vec<String>>,
926+
/// Called directly after having parsed an external `mod foo;` in expansion.
927+
pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
925928
}
926929

927930
impl<'a> ExtCtxt<'a> {
928931
pub fn new(
929932
parse_sess: &'a ParseSess,
930933
ecfg: expand::ExpansionConfig<'a>,
931934
resolver: &'a mut dyn Resolver,
935+
extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
932936
) -> ExtCtxt<'a> {
933937
ExtCtxt {
934938
parse_sess,
935939
ecfg,
936-
root_path: PathBuf::new(),
937940
resolver,
941+
extern_mod_loaded,
942+
root_path: PathBuf::new(),
938943
current_expansion: ExpansionData {
939944
id: ExpnId::root(),
940945
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};
@@ -1366,59 +1366,83 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13661366
.make_items();
13671367
}
13681368

1369+
let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck.
1370+
let ident = item.ident;
1371+
let span = item.span;
1372+
13691373
match item.kind {
13701374
ast::ItemKind::MacCall(..) => {
1375+
item.attrs = attrs;
13711376
self.check_attributes(&item.attrs);
13721377
item.and_then(|item| match item.kind {
13731378
ItemKind::MacCall(mac) => self
1374-
.collect(
1375-
AstFragmentKind::Items,
1376-
InvocationKind::Bang { mac, span: item.span },
1377-
)
1379+
.collect(AstFragmentKind::Items, InvocationKind::Bang { mac, span })
13781380
.make_items(),
13791381
_ => unreachable!(),
13801382
})
13811383
}
1382-
ast::ItemKind::Mod(ast::Mod { inner, inline, .. })
1383-
if item.ident != Ident::invalid() =>
1384-
{
1385-
let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
1384+
ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => {
1385+
let sess = self.cx.parse_sess;
1386+
let orig_ownership = self.cx.current_expansion.directory_ownership;
13861387
let mut module = (*self.cx.current_expansion.module).clone();
1387-
module.mod_path.push(item.ident);
13881388

1389-
if inline {
1390-
if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) {
1391-
self.cx.current_expansion.directory_ownership =
1392-
DirectoryOwnership::Owned { relative: None };
1393-
module.directory.push(&*path.as_str());
1394-
} else {
1395-
module.directory.push(&*item.ident.as_str());
1396-
}
1389+
let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
1390+
let dir = Directory { ownership: orig_ownership, path: module.directory };
1391+
let Directory { ownership, path } = if old_mod.inline {
1392+
// Inline `mod foo { ... }`, but we still need to push directories.
1393+
item.attrs = attrs;
1394+
push_directory(ident, &item.attrs, dir)
13971395
} else {
1398-
let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner);
1399-
let mut path = match path {
1400-
FileName::Real(path) => path,
1401-
other => PathBuf::from(other.to_string()),
1396+
// We have an outline `mod foo;` so we need to parse the file.
1397+
let (new_mod, dir) =
1398+
parse_external_mod(sess, ident, span, dir, &mut attrs, pushed);
1399+
1400+
let krate = ast::Crate {
1401+
span: new_mod.inner,
1402+
module: new_mod,
1403+
attrs,
1404+
proc_macros: vec![],
14021405
};
1403-
let directory_ownership = match path.file_name().unwrap().to_str() {
1404-
Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
1405-
Some(_) => DirectoryOwnership::Owned { relative: Some(item.ident) },
1406-
None => DirectoryOwnership::UnownedViaMod,
1406+
if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
1407+
extern_mod_loaded(&krate);
1408+
}
1409+
1410+
*old_mod = krate.module;
1411+
item.attrs = krate.attrs;
1412+
// File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1413+
item = match self.configure(item) {
1414+
Some(node) => node,
1415+
None => {
1416+
if *pushed {
1417+
sess.included_mod_stack.borrow_mut().pop();
1418+
}
1419+
return Default::default();
1420+
}
14071421
};
1408-
path.pop();
1409-
module.directory = path;
1410-
self.cx.current_expansion.directory_ownership = directory_ownership;
1411-
}
1422+
dir
1423+
};
14121424

1425+
// Set the module info before we flat map.
1426+
self.cx.current_expansion.directory_ownership = ownership;
1427+
module.directory = path;
1428+
module.mod_path.push(ident);
14131429
let orig_module =
14141430
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
1431+
14151432
let result = noop_flat_map_item(item, self);
1433+
1434+
// Restore the module info.
14161435
self.cx.current_expansion.module = orig_module;
1417-
self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1436+
self.cx.current_expansion.directory_ownership = orig_ownership;
1437+
if *pushed {
1438+
sess.included_mod_stack.borrow_mut().pop();
1439+
}
14181440
result
14191441
}
1420-
1421-
_ => noop_flat_map_item(item, self),
1442+
_ => {
1443+
item.attrs = attrs;
1444+
noop_flat_map_item(item, self)
1445+
}
14221446
}
14231447
}
14241448

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)