ast: Keep expansion status for out-of-line module items
Also remove `ast::Mod` which is mostly redundant now
This commit is contained in:
parent
eb65f15c78
commit
4a88165124
14 changed files with 147 additions and 125 deletions
|
@ -2299,21 +2299,22 @@ impl FnRetTy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Module declaration.
|
#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
|
||||||
///
|
pub enum Inline {
|
||||||
/// E.g., `mod foo;` or `mod foo { .. }`.
|
Yes,
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Module item kind.
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub struct Mod {
|
pub enum ModKind {
|
||||||
/// A span from the first token past `{` to the last token until `}`.
|
/// Module with inlined definition `mod foo { ... }`,
|
||||||
/// For `mod foo;`, the inner span ranges from the first token
|
/// or with definition outlined to a separate file `mod foo;` and already loaded from it.
|
||||||
/// to the last token in the external file.
|
/// The inner span is from the first token past `{` to the last token until `}`,
|
||||||
pub inner: Span,
|
/// or from the first to the last token in the loaded file.
|
||||||
/// `unsafe` keyword accepted syntactically for macro DSLs, but not
|
Loaded(Vec<P<Item>>, Inline, Span),
|
||||||
/// semantically by Rust.
|
/// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it.
|
||||||
pub unsafety: Unsafe,
|
Unloaded,
|
||||||
pub items: Vec<P<Item>>,
|
|
||||||
/// `true` for `mod foo { .. }`; `false` for `mod foo;`.
|
|
||||||
pub inline: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Foreign module declaration.
|
/// Foreign module declaration.
|
||||||
|
@ -2710,7 +2711,9 @@ pub enum ItemKind {
|
||||||
/// A module declaration (`mod`).
|
/// A module declaration (`mod`).
|
||||||
///
|
///
|
||||||
/// E.g., `mod foo;` or `mod foo { .. }`.
|
/// E.g., `mod foo;` or `mod foo { .. }`.
|
||||||
Mod(Mod),
|
/// `unsafe` keyword on modules is accepted syntactically for macro DSLs, but not
|
||||||
|
/// semantically by Rust.
|
||||||
|
Mod(Unsafe, ModKind),
|
||||||
/// An external module (`extern`).
|
/// An external module (`extern`).
|
||||||
///
|
///
|
||||||
/// E.g., `extern {}` or `extern "C" {}`.
|
/// E.g., `extern {}` or `extern "C" {}`.
|
||||||
|
|
|
@ -913,11 +913,13 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
|
||||||
vis.visit_generics(generics);
|
vis.visit_generics(generics);
|
||||||
visit_opt(body, |body| vis.visit_block(body));
|
visit_opt(body, |body| vis.visit_block(body));
|
||||||
}
|
}
|
||||||
ItemKind::Mod(m) => {
|
ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
|
||||||
let Mod { inner, unsafety: _, items, inline: _ } = m;
|
ModKind::Loaded(items, _inline, inner_span) => {
|
||||||
vis.visit_span(inner);
|
vis.visit_span(inner_span);
|
||||||
items.flat_map_in_place(|item| vis.flat_map_item(item));
|
items.flat_map_in_place(|item| vis.flat_map_item(item));
|
||||||
}
|
}
|
||||||
|
ModKind::Unloaded => {}
|
||||||
|
},
|
||||||
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
|
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
|
||||||
ItemKind::GlobalAsm(_ga) => {}
|
ItemKind::GlobalAsm(_ga) => {}
|
||||||
ItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
|
ItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
|
||||||
|
@ -1010,7 +1012,7 @@ pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
|
||||||
id: DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
vis: item_vis,
|
vis: item_vis,
|
||||||
span,
|
span,
|
||||||
kind: ItemKind::Mod(Mod { inner: span, unsafety: Unsafe::No, items, inline: true }),
|
kind: ItemKind::Mod(Unsafe::No, ModKind::Loaded(items, Inline::Yes, span)),
|
||||||
tokens: None,
|
tokens: None,
|
||||||
});
|
});
|
||||||
let items = vis.flat_map_item(item);
|
let items = vis.flat_map_item(item);
|
||||||
|
@ -1021,7 +1023,9 @@ pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
|
||||||
} else if len == 1 {
|
} else if len == 1 {
|
||||||
let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner();
|
let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner();
|
||||||
match kind {
|
match kind {
|
||||||
ItemKind::Mod(module) => Crate { attrs, items: module.items, span, proc_macros },
|
ItemKind::Mod(_, ModKind::Loaded(items, ..)) => {
|
||||||
|
Crate { attrs, items, span, proc_macros }
|
||||||
|
}
|
||||||
_ => panic!("visitor converted a module to not a module"),
|
_ => panic!("visitor converted a module to not a module"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -290,7 +290,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
||||||
let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
|
let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
|
||||||
visitor.visit_fn(kind, item.span, item.id)
|
visitor.visit_fn(kind, item.span, item.id)
|
||||||
}
|
}
|
||||||
ItemKind::Mod(ref module) => walk_list!(visitor, visit_item, &module.items),
|
ItemKind::Mod(_unsafety, ref mod_kind) => match mod_kind {
|
||||||
|
ModKind::Loaded(items, _inline, _inner_span) => {
|
||||||
|
walk_list!(visitor, visit_item, items)
|
||||||
|
}
|
||||||
|
ModKind::Unloaded => {}
|
||||||
|
},
|
||||||
ItemKind::ForeignMod(ref foreign_module) => {
|
ItemKind::ForeignMod(ref foreign_module) => {
|
||||||
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
|
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,7 +314,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
hir::ItemKind::Fn(sig, generics, body_id)
|
hir::ItemKind::Fn(sig, generics, body_id)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(&m.items, m.inner)),
|
ItemKind::Mod(_, ref mod_kind) => match mod_kind {
|
||||||
|
ModKind::Loaded(items, _, inner_span) => {
|
||||||
|
hir::ItemKind::Mod(self.lower_mod(items, *inner_span))
|
||||||
|
}
|
||||||
|
ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
|
||||||
|
},
|
||||||
ItemKind::ForeignMod(ref fm) => {
|
ItemKind::ForeignMod(ref fm) => {
|
||||||
if fm.abi.is_none() {
|
if fm.abi.is_none() {
|
||||||
self.maybe_lint_missing_abi(span, id, abi::Abi::C);
|
self.maybe_lint_missing_abi(span, id, abi::Abi::C);
|
||||||
|
|
|
@ -1054,12 +1054,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
walk_list!(self, visit_attribute, &item.attrs);
|
walk_list!(self, visit_attribute, &item.attrs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ItemKind::Mod(Mod { inline, unsafety, .. }) => {
|
ItemKind::Mod(unsafety, ref mod_kind) => {
|
||||||
if let Unsafe::Yes(span) = unsafety {
|
if let Unsafe::Yes(span) = unsafety {
|
||||||
self.err_handler().span_err(span, "module cannot be declared unsafe");
|
self.err_handler().span_err(span, "module cannot be declared unsafe");
|
||||||
}
|
}
|
||||||
// Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
|
// Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
|
||||||
if !inline && !self.session.contains_name(&item.attrs, sym::path) {
|
if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _))
|
||||||
|
&& !self.session.contains_name(&item.attrs, sym::path)
|
||||||
|
{
|
||||||
self.check_mod_file_item_asciionly(item.ident);
|
self.check_mod_file_item_asciionly(item.ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use rustc_ast::util::classify;
|
||||||
use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
|
use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
|
||||||
use rustc_ast::util::parser::{self, AssocOp, Fixity};
|
use rustc_ast::util::parser::{self, AssocOp, Fixity};
|
||||||
use rustc_ast::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
|
use rustc_ast::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
|
||||||
use rustc_ast::{GenericArg, MacArgs};
|
use rustc_ast::{GenericArg, MacArgs, ModKind};
|
||||||
use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier};
|
use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier};
|
||||||
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
|
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
|
||||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
|
@ -87,7 +87,6 @@ pub struct State<'a> {
|
||||||
pub s: pp::Printer,
|
pub s: pp::Printer,
|
||||||
comments: Option<Comments<'a>>,
|
comments: Option<Comments<'a>>,
|
||||||
ann: &'a (dyn PpAnn + 'a),
|
ann: &'a (dyn PpAnn + 'a),
|
||||||
is_expanded: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
crate const INDENT_UNIT: usize = 4;
|
crate const INDENT_UNIT: usize = 4;
|
||||||
|
@ -103,12 +102,8 @@ pub fn print_crate<'a>(
|
||||||
is_expanded: bool,
|
is_expanded: bool,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut s = State {
|
let mut s =
|
||||||
s: pp::mk_printer(),
|
State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann };
|
||||||
comments: Some(Comments::new(sm, filename, input)),
|
|
||||||
ann,
|
|
||||||
is_expanded,
|
|
||||||
};
|
|
||||||
|
|
||||||
if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
|
if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
|
||||||
// We need to print `#![no_std]` (and its feature gate) so that
|
// We need to print `#![no_std]` (and its feature gate) so that
|
||||||
|
@ -856,7 +851,7 @@ impl<'a> PrintState<'a> for State<'a> {
|
||||||
|
|
||||||
impl<'a> State<'a> {
|
impl<'a> State<'a> {
|
||||||
pub fn new() -> State<'a> {
|
pub fn new() -> State<'a> {
|
||||||
State { s: pp::mk_printer(), comments: None, ann: &NoAnn, is_expanded: false }
|
State { s: pp::mk_printer(), comments: None, ann: &NoAnn }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synthesizes a comment that was not textually present in the original source
|
// Synthesizes a comment that was not textually present in the original source
|
||||||
|
@ -1134,26 +1129,29 @@ impl<'a> State<'a> {
|
||||||
let body = body.as_deref();
|
let body = body.as_deref();
|
||||||
self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs);
|
self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs);
|
||||||
}
|
}
|
||||||
ast::ItemKind::Mod(ref _mod) => {
|
ast::ItemKind::Mod(unsafety, ref mod_kind) => {
|
||||||
self.head(self.to_string(|s| {
|
self.head(self.to_string(|s| {
|
||||||
s.print_visibility(&item.vis);
|
s.print_visibility(&item.vis);
|
||||||
s.print_unsafety(_mod.unsafety);
|
s.print_unsafety(unsafety);
|
||||||
s.word("mod");
|
s.word("mod");
|
||||||
}));
|
}));
|
||||||
self.print_ident(item.ident);
|
self.print_ident(item.ident);
|
||||||
|
|
||||||
if _mod.inline || self.is_expanded {
|
match mod_kind {
|
||||||
self.nbsp();
|
ModKind::Loaded(items, ..) => {
|
||||||
self.bopen();
|
self.nbsp();
|
||||||
self.print_inner_attributes(&item.attrs);
|
self.bopen();
|
||||||
for item in &_mod.items {
|
self.print_inner_attributes(&item.attrs);
|
||||||
self.print_item(item);
|
for item in items {
|
||||||
|
self.print_item(item);
|
||||||
|
}
|
||||||
|
self.bclose(item.span);
|
||||||
|
}
|
||||||
|
ModKind::Unloaded => {
|
||||||
|
self.s.word(";");
|
||||||
|
self.end(); // end inner head-block
|
||||||
|
self.end(); // end outer head-block
|
||||||
}
|
}
|
||||||
self.bclose(item.span);
|
|
||||||
} else {
|
|
||||||
self.s.word(";");
|
|
||||||
self.end(); // end inner head-block
|
|
||||||
self.end(); // end outer head-block
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ItemKind::ForeignMod(ref nmod) => {
|
ast::ItemKind::ForeignMod(ref nmod) => {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
// Code that generates a test runner to run all the tests in a crate
|
// Code that generates a test runner to run all the tests in a crate
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::attr;
|
|
||||||
use rustc_ast::entry::EntryPointType;
|
use rustc_ast::entry::EntryPointType;
|
||||||
use rustc_ast::mut_visit::{ExpectOne, *};
|
use rustc_ast::mut_visit::{ExpectOne, *};
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
|
use rustc_ast::{attr, ModKind};
|
||||||
use rustc_expand::base::{ExtCtxt, ResolverExpand};
|
use rustc_expand::base::{ExtCtxt, ResolverExpand};
|
||||||
use rustc_expand::expand::{AstFragment, ExpansionConfig};
|
use rustc_expand::expand::{AstFragment, ExpansionConfig};
|
||||||
use rustc_feature::Features;
|
use rustc_feature::Features;
|
||||||
|
@ -106,10 +106,6 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
|
||||||
if let ast::ItemKind::Mod(..) = item.kind {
|
if let ast::ItemKind::Mod(..) = item.kind {
|
||||||
let tests = mem::take(&mut self.tests);
|
let tests = mem::take(&mut self.tests);
|
||||||
noop_visit_item_kind(&mut item.kind, self);
|
noop_visit_item_kind(&mut item.kind, self);
|
||||||
let module = match item.kind {
|
|
||||||
ast::ItemKind::Mod(module) => module,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
let mut tests = mem::replace(&mut self.tests, tests);
|
let mut tests = mem::replace(&mut self.tests, tests);
|
||||||
|
|
||||||
if !tests.is_empty() {
|
if !tests.is_empty() {
|
||||||
|
@ -117,8 +113,12 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
|
||||||
if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id };
|
if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id };
|
||||||
// Create an identifier that will hygienically resolve the test
|
// Create an identifier that will hygienically resolve the test
|
||||||
// case name, even in another module.
|
// case name, even in another module.
|
||||||
|
let inner_span = match item.kind {
|
||||||
|
ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) => span,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
|
let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
|
||||||
module.inner,
|
inner_span,
|
||||||
AstPass::TestHarness,
|
AstPass::TestHarness,
|
||||||
&[],
|
&[],
|
||||||
Some(parent),
|
Some(parent),
|
||||||
|
@ -130,7 +130,6 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
|
||||||
}
|
}
|
||||||
self.cx.test_cases.extend(tests);
|
self.cx.test_cases.extend(tests);
|
||||||
}
|
}
|
||||||
item.kind = ast::ItemKind::Mod(module);
|
|
||||||
}
|
}
|
||||||
smallvec![P(item)]
|
smallvec![P(item)]
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token;
|
use rustc_ast::token;
|
||||||
use rustc_ast::tokenstream::TokenStream;
|
use rustc_ast::tokenstream::TokenStream;
|
||||||
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
||||||
use rustc_ast::{AttrItem, AttrStyle, Block, ItemKind, LitKind, MacArgs};
|
use rustc_ast::{AttrItem, AttrStyle, Block, Inline, ItemKind, LitKind, MacArgs};
|
||||||
use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, NestedMetaItem};
|
use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
|
||||||
use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
|
use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
|
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
|
||||||
|
@ -367,12 +367,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
let krate_item = AstFragment::Items(smallvec![P(ast::Item {
|
let krate_item = AstFragment::Items(smallvec![P(ast::Item {
|
||||||
attrs: krate.attrs,
|
attrs: krate.attrs,
|
||||||
span: krate.span,
|
span: krate.span,
|
||||||
kind: ast::ItemKind::Mod(ast::Mod {
|
kind: ast::ItemKind::Mod(
|
||||||
inner: krate.span,
|
Unsafe::No,
|
||||||
unsafety: Unsafe::No,
|
ModKind::Loaded(krate.items, Inline::Yes, krate.span)
|
||||||
items: krate.items,
|
),
|
||||||
inline: true
|
|
||||||
}),
|
|
||||||
ident: Ident::invalid(),
|
ident: Ident::invalid(),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
vis: ast::Visibility {
|
vis: ast::Visibility {
|
||||||
|
@ -384,9 +382,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
})]);
|
})]);
|
||||||
|
|
||||||
match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
|
match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
|
||||||
Some(ast::Item { attrs, kind: ast::ItemKind::Mod(module), .. }) => {
|
Some(ast::Item {
|
||||||
|
attrs,
|
||||||
|
kind: ast::ItemKind::Mod(_, ModKind::Loaded(items, ..)),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
krate.attrs = attrs;
|
krate.attrs = attrs;
|
||||||
krate.items = module.items;
|
krate.items = items;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Resolution failed so we return an empty expansion
|
// Resolution failed so we return an empty expansion
|
||||||
|
@ -809,7 +811,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
|
impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
|
||||||
fn visit_item(&mut self, item: &'ast ast::Item) {
|
fn visit_item(&mut self, item: &'ast ast::Item) {
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
ast::ItemKind::Mod(module) if !module.inline => {
|
ast::ItemKind::Mod(_, mod_kind)
|
||||||
|
if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
|
||||||
|
{
|
||||||
feature_err(
|
feature_err(
|
||||||
self.parse_sess,
|
self.parse_sess,
|
||||||
sym::proc_macro_hygiene,
|
sym::proc_macro_hygiene,
|
||||||
|
@ -1266,47 +1270,47 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => {
|
ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => {
|
||||||
let sess = &self.cx.sess.parse_sess;
|
let sess = &self.cx.sess.parse_sess;
|
||||||
let orig_ownership = self.cx.current_expansion.directory_ownership;
|
let orig_ownership = self.cx.current_expansion.directory_ownership;
|
||||||
let mut module = (*self.cx.current_expansion.module).clone();
|
let mut module = (*self.cx.current_expansion.module).clone();
|
||||||
|
|
||||||
let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
|
let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
|
||||||
let dir = Directory { ownership: orig_ownership, path: module.directory };
|
let dir = Directory { ownership: orig_ownership, path: module.directory };
|
||||||
let Directory { ownership, path } = if old_mod.inline {
|
let Directory { ownership, path } = match mod_kind {
|
||||||
// Inline `mod foo { ... }`, but we still need to push directories.
|
ModKind::Loaded(_, Inline::Yes, _) => {
|
||||||
item.attrs = attrs;
|
// Inline `mod foo { ... }`, but we still need to push directories.
|
||||||
push_directory(&self.cx.sess, ident, &item.attrs, dir)
|
item.attrs = attrs;
|
||||||
} else {
|
push_directory(&self.cx.sess, ident, &item.attrs, dir)
|
||||||
// We have an outline `mod foo;` so we need to parse the file.
|
|
||||||
let (ast::Mod { unsafety, inline, items, inner }, dir) = parse_external_mod(
|
|
||||||
&self.cx.sess,
|
|
||||||
ident,
|
|
||||||
span,
|
|
||||||
old_mod.unsafety,
|
|
||||||
dir,
|
|
||||||
&mut attrs,
|
|
||||||
pushed,
|
|
||||||
);
|
|
||||||
|
|
||||||
let krate = ast::Crate { attrs, items, span: inner, proc_macros: vec![] };
|
|
||||||
if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
|
|
||||||
extern_mod_loaded(&krate, ident);
|
|
||||||
}
|
}
|
||||||
|
ModKind::Loaded(_, Inline::No, _) => {
|
||||||
|
panic!("`mod` item is loaded from a file for the second time")
|
||||||
|
}
|
||||||
|
ModKind::Unloaded => {
|
||||||
|
// We have an outline `mod foo;` so we need to parse the file.
|
||||||
|
let (items, inner_span, dir) =
|
||||||
|
parse_external_mod(&self.cx.sess, ident, span, dir, &mut attrs, pushed);
|
||||||
|
|
||||||
*old_mod = ast::Mod { unsafety, inline, items: krate.items, inner };
|
let krate =
|
||||||
item.attrs = krate.attrs;
|
ast::Crate { attrs, items, span: inner_span, proc_macros: vec![] };
|
||||||
// File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
|
if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
|
||||||
item = match self.configure(item) {
|
extern_mod_loaded(&krate, ident);
|
||||||
Some(node) => node,
|
|
||||||
None => {
|
|
||||||
if *pushed {
|
|
||||||
sess.included_mod_stack.borrow_mut().pop();
|
|
||||||
}
|
|
||||||
return Default::default();
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
dir
|
*mod_kind = ModKind::Loaded(krate.items, Inline::No, inner_span);
|
||||||
|
item.attrs = krate.attrs;
|
||||||
|
// File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
|
||||||
|
item = match self.configure(item) {
|
||||||
|
Some(node) => node,
|
||||||
|
None => {
|
||||||
|
if *pushed {
|
||||||
|
sess.included_mod_stack.borrow_mut().pop();
|
||||||
|
}
|
||||||
|
return Default::default();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
dir
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the module info before we flat map.
|
// Set the module info before we flat map.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use rustc_ast::{token, Attribute, Mod, Unsafe};
|
use rustc_ast::ptr::P;
|
||||||
|
use rustc_ast::{token, Attribute, Item};
|
||||||
use rustc_errors::{struct_span_err, PResult};
|
use rustc_errors::{struct_span_err, PResult};
|
||||||
use rustc_parse::new_parser_from_file;
|
use rustc_parse::new_parser_from_file;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
|
@ -42,11 +43,10 @@ crate fn parse_external_mod(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
id: Ident,
|
id: Ident,
|
||||||
span: Span, // The span to blame on errors.
|
span: Span, // The span to blame on errors.
|
||||||
unsafety: Unsafe,
|
|
||||||
Directory { mut ownership, path }: Directory,
|
Directory { mut ownership, path }: Directory,
|
||||||
attrs: &mut Vec<Attribute>,
|
attrs: &mut Vec<Attribute>,
|
||||||
pop_mod_stack: &mut bool,
|
pop_mod_stack: &mut bool,
|
||||||
) -> (Mod, Directory) {
|
) -> (Vec<P<Item>>, Span, Directory) {
|
||||||
// We bail on the first error, but that error does not cause a fatal error... (1)
|
// We bail on the first error, but that error does not cause a fatal error... (1)
|
||||||
let result: PResult<'_, _> = try {
|
let result: PResult<'_, _> = try {
|
||||||
// Extract the file path and the new ownership.
|
// Extract the file path and the new ownership.
|
||||||
|
@ -62,25 +62,22 @@ crate fn parse_external_mod(
|
||||||
|
|
||||||
// Actually parse the external file as a module.
|
// Actually parse the external file as a module.
|
||||||
let mut parser = new_parser_from_file(&sess.parse_sess, &mp.path, Some(span));
|
let mut parser = new_parser_from_file(&sess.parse_sess, &mp.path, Some(span));
|
||||||
let (inner_attrs, items, inner) = parser.parse_mod(&token::Eof)?;
|
let (mut inner_attrs, items, inner_span) = parser.parse_mod(&token::Eof)?;
|
||||||
(Mod { unsafety, inline: false, items, inner }, inner_attrs)
|
attrs.append(&mut inner_attrs);
|
||||||
|
(items, inner_span)
|
||||||
};
|
};
|
||||||
// (1) ...instead, we return a dummy module.
|
// (1) ...instead, we return a dummy module.
|
||||||
let (module, mut new_attrs) = result.map_err(|mut err| err.emit()).unwrap_or_else(|_| {
|
let (items, inner_span) = result.map_err(|mut err| err.emit()).unwrap_or_default();
|
||||||
let module = Mod { inner: Span::default(), unsafety, items: Vec::new(), inline: false };
|
|
||||||
(module, Vec::new())
|
|
||||||
});
|
|
||||||
attrs.append(&mut new_attrs);
|
|
||||||
|
|
||||||
// Extract the directory path for submodules of `module`.
|
// Extract the directory path for submodules of the module.
|
||||||
let path = sess.source_map().span_to_unmapped_path(module.inner);
|
let path = sess.source_map().span_to_unmapped_path(inner_span);
|
||||||
let mut path = match path {
|
let mut path = match path {
|
||||||
FileName::Real(name) => name.into_local_path(),
|
FileName::Real(name) => name.into_local_path(),
|
||||||
other => PathBuf::from(other.to_string()),
|
other => PathBuf::from(other.to_string()),
|
||||||
};
|
};
|
||||||
path.pop();
|
path.pop();
|
||||||
|
|
||||||
(module, Directory { ownership, path })
|
(items, inner_span, Directory { ownership, path })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_on_circular_module<'a>(
|
fn error_on_circular_module<'a>(
|
||||||
|
|
|
@ -309,8 +309,8 @@ fn out_of_line_mod() {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if let ast::ItemKind::Mod(ref m) = item.kind {
|
if let ast::ItemKind::Mod(_, ref mod_kind) = item.kind {
|
||||||
assert!(m.items.len() == 2);
|
assert!(matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2));
|
||||||
} else {
|
} else {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,14 +35,16 @@ impl<'a> Parser<'a> {
|
||||||
let unsafety = self.parse_unsafety();
|
let unsafety = self.parse_unsafety();
|
||||||
self.expect_keyword(kw::Mod)?;
|
self.expect_keyword(kw::Mod)?;
|
||||||
let id = self.parse_ident()?;
|
let id = self.parse_ident()?;
|
||||||
let ((mut inner_attrs, items, inner), inline) = if self.eat(&token::Semi) {
|
let mod_kind = if self.eat(&token::Semi) {
|
||||||
((Vec::new(), Vec::new(), Span::default()), false)
|
ModKind::Unloaded
|
||||||
} else {
|
} else {
|
||||||
self.expect(&token::OpenDelim(token::Brace))?;
|
self.expect(&token::OpenDelim(token::Brace))?;
|
||||||
(self.parse_mod(&token::CloseDelim(token::Brace))?, true)
|
let (mut inner_attrs, items, inner_span) =
|
||||||
|
self.parse_mod(&token::CloseDelim(token::Brace))?;
|
||||||
|
attrs.append(&mut inner_attrs);
|
||||||
|
ModKind::Loaded(items, Inline::Yes, inner_span)
|
||||||
};
|
};
|
||||||
attrs.append(&mut inner_attrs);
|
Ok((id, ItemKind::Mod(unsafety, mod_kind)))
|
||||||
Ok((id, ItemKind::Mod(Mod { unsafety, inline, items, inner })))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the contents of a module (inner attributes followed by module items).
|
/// Parses the contents of a module (inner attributes followed by module items).
|
||||||
|
|
|
@ -1023,7 +1023,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::Mod(_) | ItemKind::ForeignMod(_) => {
|
ItemKind::Mod(..) | ItemKind::ForeignMod(_) => {
|
||||||
self.with_scope(item.id, |this| {
|
self.with_scope(item.id, |this| {
|
||||||
visit::walk_item(this, item);
|
visit::walk_item(this, item);
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,7 +29,7 @@ use rustc_ast::unwrap_or;
|
||||||
use rustc_ast::visit::{self, Visitor};
|
use rustc_ast::visit::{self, Visitor};
|
||||||
use rustc_ast::{self as ast, NodeId};
|
use rustc_ast::{self as ast, NodeId};
|
||||||
use rustc_ast::{Crate, CRATE_NODE_ID};
|
use rustc_ast::{Crate, CRATE_NODE_ID};
|
||||||
use rustc_ast::{ItemKind, Path};
|
use rustc_ast::{ItemKind, ModKind, Path};
|
||||||
use rustc_ast_lowering::ResolverAstLowering;
|
use rustc_ast_lowering::ResolverAstLowering;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||||
|
@ -339,8 +339,8 @@ impl UsePlacementFinder {
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
|
impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
|
||||||
fn visit_item(&mut self, item: &'tcx ast::Item) {
|
fn visit_item(&mut self, item: &'tcx ast::Item) {
|
||||||
if let ItemKind::Mod(module) = &item.kind {
|
if let ItemKind::Mod(_, ModKind::Loaded(items, ..)) = &item.kind {
|
||||||
if let ControlFlow::Break(..) = self.check_mod(&module.items, item.id) {
|
if let ControlFlow::Break(..) = self.check_mod(items, item.id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,9 +241,12 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
||||||
&& eq_generics(lg, rg)
|
&& eq_generics(lg, rg)
|
||||||
&& both(lb, rb, |l, r| eq_block(l, r))
|
&& both(lb, rb, |l, r| eq_block(l, r))
|
||||||
}
|
}
|
||||||
(Mod(l), Mod(r)) => {
|
(Mod(lu, lmk), Mod(ru, rmk)) => lu == ru && match (lmk, rmk) {
|
||||||
l.inline == r.inline && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_item_kind))
|
(ModKind::Loaded(litems, linline, _), ModKind::Loaded(ritems, rinline, _)) =>
|
||||||
}
|
linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind)),
|
||||||
|
(ModKind::Unloaded, ModKind::Unloaded) => true,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
(ForeignMod(l), ForeignMod(r)) => {
|
(ForeignMod(l), ForeignMod(r)) => {
|
||||||
both(&l.abi, &r.abi, |l, r| eq_str_lit(l, r))
|
both(&l.abi, &r.abi, |l, r| eq_str_lit(l, r))
|
||||||
&& over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind))
|
&& over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue