1
Fork 0

Rollup merge of #82238 - petrochenkov:nocratemod, r=Aaron1011

ast: Keep expansion status for out-of-line module items

I.e. whether a module `mod foo;` is already loaded from a file or not.
This is a pre-requisite to correctly treating inner attributes on such modules (https://github.com/rust-lang/rust/issues/81661).

With this change AST structures for `mod` items diverge even more for AST structure for the crate root, which previously used `ast::Mod`.
Therefore this PR removes `ast::Mod` from `ast::Crate` in the first commit, these two things are sufficiently different from each other, at least at syntactic level.
Customization points for visiting a "`mod` item or crate root" were also removed from AST visitors (`fn visit_mod`).
`ast::Mod` itself was refactored away in the second commit in favor of `ItemKind::Mod(Unsafe, ModKind)`.
This commit is contained in:
Dylan DPC 2021-02-19 02:49:08 +01:00 committed by GitHub
commit 30f39fee9d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 227 additions and 270 deletions

View file

@ -486,8 +486,8 @@ pub struct WhereEqPredicate {
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
pub struct Crate { pub struct Crate {
pub module: Mod,
pub attrs: Vec<Attribute>, pub attrs: Vec<Attribute>,
pub items: Vec<P<Item>>,
pub span: Span, pub span: Span,
/// The order of items in the HIR is unrelated to the order of /// The order of items in the HIR is unrelated to the order of
/// items in the AST. However, we generate proc macro harnesses /// items in the AST. However, we generate proc macro harnesses
@ -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" {}`.

View file

@ -170,10 +170,6 @@ pub trait MutVisitor: Sized {
noop_visit_ty_constraint(t, self); noop_visit_ty_constraint(t, self);
} }
fn visit_mod(&mut self, m: &mut Mod) {
noop_visit_mod(m, self);
}
fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) { fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) {
noop_visit_foreign_mod(nm, self); noop_visit_foreign_mod(nm, self);
} }
@ -917,7 +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) => vis.visit_mod(m), ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
ModKind::Loaded(items, _inline, inner_span) => {
vis.visit_span(inner_span);
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)) => {
@ -998,14 +1000,10 @@ pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
vis.visit_asyncness(asyncness); vis.visit_asyncness(asyncness);
} }
pub fn noop_visit_mod<T: MutVisitor>(module: &mut Mod, vis: &mut T) { // FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible,
let Mod { inner, unsafety: _, items, inline: _ } = module; // or make crate visiting first class if necessary.
vis.visit_span(inner);
items.flat_map_in_place(|item| vis.flat_map_item(item));
}
pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) { pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
visit_clobber(krate, |Crate { module, attrs, span, proc_macros }| { visit_clobber(krate, |Crate { attrs, items, span, proc_macros }| {
let item_vis = let item_vis =
Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None }; Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None };
let item = P(Item { let item = P(Item {
@ -1014,19 +1012,20 @@ 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(module), 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);
let len = items.len(); let len = items.len();
if len == 0 { if len == 0 {
let module = Mod { inner: span, unsafety: Unsafe::No, items: vec![], inline: true }; Crate { attrs: vec![], items: vec![], span, proc_macros }
Crate { module, attrs: vec![], span, proc_macros }
} 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 { module, attrs, 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 {

View file

@ -74,7 +74,7 @@ impl<'a> FnKind<'a> {
/// Each method of the `Visitor` trait is a hook to be potentially /// Each method of the `Visitor` trait is a hook to be potentially
/// overridden. Each method's default implementation recursively visits /// overridden. Each method's default implementation recursively visits
/// the substructure of the input via the corresponding `walk` method; /// the substructure of the input via the corresponding `walk` method;
/// e.g., the `visit_mod` method by default calls `visit::walk_mod`. /// e.g., the `visit_item` method by default calls `visit::walk_item`.
/// ///
/// If you want to ensure that your code handles every variant /// If you want to ensure that your code handles every variant
/// explicitly, you need to override each method. (And you also need /// explicitly, you need to override each method. (And you also need
@ -87,9 +87,6 @@ pub trait Visitor<'ast>: Sized {
fn visit_ident(&mut self, ident: Ident) { fn visit_ident(&mut self, ident: Ident) {
walk_ident(self, ident); walk_ident(self, ident);
} }
fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _attrs: &[Attribute], _n: NodeId) {
walk_mod(self, m);
}
fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { fn visit_foreign_item(&mut self, i: &'ast ForeignItem) {
walk_foreign_item(self, i) walk_foreign_item(self, i)
} }
@ -238,14 +235,10 @@ pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, ident: Ident) {
} }
pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) { pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
visitor.visit_mod(&krate.module, krate.span, &krate.attrs, CRATE_NODE_ID); walk_list!(visitor, visit_item, &krate.items);
walk_list!(visitor, visit_attribute, &krate.attrs); walk_list!(visitor, visit_attribute, &krate.attrs);
} }
pub fn walk_mod<'a, V: Visitor<'a>>(visitor: &mut V, module: &'a Mod) {
walk_list!(visitor, visit_item, &module.items);
}
pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) { pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) {
for attr in local.attrs.iter() { for attr in local.attrs.iter() {
visitor.visit_attribute(attr); visitor.visit_attribute(attr);
@ -297,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) => visitor.visit_mod(module, item.span, &item.attrs, item.id), 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);
} }

View file

@ -15,11 +15,11 @@ use rustc_span::source_map::{respan, DesugaringKind};
use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span; use rustc_span::Span;
use rustc_target::spec::abi; use rustc_target::spec::abi;
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use std::collections::BTreeSet;
use tracing::debug; use tracing::debug;
use std::mem;
pub(super) struct ItemLowerer<'a, 'lowering, 'hir> { pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>, pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>,
} }
@ -34,25 +34,6 @@ impl ItemLowerer<'_, '_, '_> {
} }
impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
fn visit_mod(&mut self, m: &'a Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
let def_id = self.lctx.lower_node_id(n).expect_owner();
self.lctx.modules.insert(
def_id,
hir::ModuleItems {
items: BTreeSet::new(),
trait_items: BTreeSet::new(),
impl_items: BTreeSet::new(),
foreign_items: BTreeSet::new(),
},
);
let old = self.lctx.current_module;
self.lctx.current_module = def_id;
visit::walk_mod(self, m);
self.lctx.current_module = old;
}
fn visit_item(&mut self, item: &'a Item) { fn visit_item(&mut self, item: &'a Item) {
let mut item_hir_id = None; let mut item_hir_id = None;
self.lctx.with_hir_id_owner(item.id, |lctx| { self.lctx.with_hir_id_owner(item.id, |lctx| {
@ -67,10 +48,18 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
if let Some(hir_id) = item_hir_id { if let Some(hir_id) = item_hir_id {
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
let this = &mut ItemLowerer { lctx: this }; let this = &mut ItemLowerer { lctx: this };
if let ItemKind::Impl(box ImplKind { ref of_trait, .. }) = item.kind { match item.kind {
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item)); ItemKind::Mod(..) => {
} else { let def_id = this.lctx.lower_node_id(item.id).expect_owner();
visit::walk_item(this, item); let old_current_module =
mem::replace(&mut this.lctx.current_module, def_id);
visit::walk_item(this, item);
this.lctx.current_module = old_current_module;
}
ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
}
_ => visit::walk_item(this, item),
} }
}); });
} }
@ -94,13 +83,13 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
let hir_item = lctx.lower_trait_item(item); let hir_item = lctx.lower_trait_item(item);
let id = hir_item.trait_item_id(); let id = hir_item.trait_item_id();
lctx.trait_items.insert(id, hir_item); lctx.trait_items.insert(id, hir_item);
lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id); lctx.modules.entry(lctx.current_module).or_default().trait_items.insert(id);
} }
AssocCtxt::Impl => { AssocCtxt::Impl => {
let hir_item = lctx.lower_impl_item(item); let hir_item = lctx.lower_impl_item(item);
let id = hir_item.impl_item_id(); let id = hir_item.impl_item_id();
lctx.impl_items.insert(id, hir_item); lctx.impl_items.insert(id, hir_item);
lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id); lctx.modules.entry(lctx.current_module).or_default().impl_items.insert(id);
} }
}); });
@ -113,7 +102,7 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
let hir_item = lctx.lower_foreign_item(item); let hir_item = lctx.lower_foreign_item(item);
let id = hir_item.foreign_item_id(); let id = hir_item.foreign_item_id();
lctx.foreign_items.insert(id, hir_item); lctx.foreign_items.insert(id, hir_item);
lctx.modules.get_mut(&lctx.current_module).unwrap().foreign_items.insert(id); lctx.modules.entry(lctx.current_module).or_default().foreign_items.insert(id);
}); });
visit::walk_foreign_item(self, item); visit::walk_foreign_item(self, item);
@ -157,7 +146,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut self, &mut self,
f: impl FnOnce(&mut LoweringContext<'_, '_>) -> T, f: impl FnOnce(&mut LoweringContext<'_, '_>) -> T,
) -> T { ) -> T {
let old_in_scope_lifetimes = std::mem::replace(&mut self.in_scope_lifetimes, vec![]); let old_in_scope_lifetimes = mem::replace(&mut self.in_scope_lifetimes, vec![]);
// this vector is only used when walking over impl headers, // this vector is only used when walking over impl headers,
// input types, and the like, and should not be non-empty in // input types, and the like, and should not be non-empty in
@ -172,12 +161,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
res res
} }
pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod<'hir> { pub(super) fn lower_mod(&mut self, items: &[P<Item>], inner: Span) -> hir::Mod<'hir> {
hir::Mod { hir::Mod {
inner: m.inner, inner,
item_ids: self item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_id(x))),
.arena
.alloc_from_iter(m.items.iter().flat_map(|x| self.lower_item_id(x))),
} }
} }
@ -327,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)), 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);

View file

@ -560,7 +560,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c); visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c); visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
let module = self.lower_mod(&c.module); let module = self.lower_mod(&c.items, c.span);
let attrs = self.lower_attrs(&c.attrs); let attrs = self.lower_attrs(&c.attrs);
let body_ids = body_ids(&self.bodies); let body_ids = body_ids(&self.bodies);
let proc_macros = let proc_macros =
@ -608,7 +608,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId { fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId {
let id = hir::ItemId { def_id: item.def_id }; let id = hir::ItemId { def_id: item.def_id };
self.items.insert(id, item); self.items.insert(id, item);
self.modules.get_mut(&self.current_module).unwrap().items.insert(id); self.modules.entry(self.current_module).or_default().items.insert(id);
id id
} }

View file

@ -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);
} }
} }

View file

@ -20,10 +20,6 @@ impl<'ast> Visitor<'ast> for NodeCounter {
self.count += 1; self.count += 1;
walk_ident(self, ident); walk_ident(self, ident);
} }
fn visit_mod(&mut self, m: &Mod, _s: Span, _a: &[Attribute], _n: NodeId) {
self.count += 1;
walk_mod(self, m)
}
fn visit_foreign_item(&mut self, i: &ForeignItem) { fn visit_foreign_item(&mut self, i: &ForeignItem) {
self.count += 1; self.count += 1;
walk_foreign_item(self, i) walk_foreign_item(self, i)

View file

@ -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
@ -132,7 +127,10 @@ pub fn print_crate<'a>(
} }
} }
s.print_mod(&krate.module, &krate.attrs); s.print_inner_attributes(&krate.attrs);
for item in &krate.items {
s.print_item(item);
}
s.print_remaining_comments(); s.print_remaining_comments();
s.ann.post(&mut s, AnnNode::Crate(krate)); s.ann.post(&mut s, AnnNode::Crate(krate));
s.s.eof() s.s.eof()
@ -853,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
@ -891,13 +889,6 @@ impl<'a> State<'a> {
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span) self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
} }
pub fn print_mod(&mut self, _mod: &ast::Mod, attrs: &[ast::Attribute]) {
self.print_inner_attributes(attrs);
for item in &_mod.items {
self.print_item(item);
}
}
crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]) { crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]) {
self.print_inner_attributes(attrs); self.print_inner_attributes(attrs);
for item in &nmod.items { for item in &nmod.items {
@ -1139,23 +1130,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_mod(_mod, &item.attrs); self.bopen();
self.bclose(item.span); self.print_inner_attributes(&item.attrs);
} else { for item in items {
self.s.word(";"); self.print_item(item);
self.end(); // end inner head-block }
self.end(); // end outer head-block self.bclose(item.span);
}
ModKind::Unloaded => {
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) => {

View file

@ -91,7 +91,7 @@ pub fn inject(
} }
let decls = mk_decls(&mut krate, &mut cx, &macros); let decls = mk_decls(&mut krate, &mut cx, &macros);
krate.module.items.push(decls); krate.items.push(decls);
krate krate
} }

View file

@ -44,7 +44,7 @@ pub fn inject(
// .rev() to preserve ordering above in combination with insert(0, ...) // .rev() to preserve ordering above in combination with insert(0, ...)
for &name in names.iter().rev() { for &name in names.iter().rev() {
let ident = if rust_2018 { Ident::new(name, span) } else { Ident::new(name, call_site) }; let ident = if rust_2018 { Ident::new(name, span) } else { Ident::new(name, call_site) };
krate.module.items.insert( krate.items.insert(
0, 0,
cx.item( cx.item(
span, span,
@ -79,7 +79,7 @@ pub fn inject(
})), })),
); );
krate.module.items.insert(0, use_item); krate.items.insert(0, use_item);
krate krate
} }

View file

@ -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;
@ -89,7 +89,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
noop_visit_crate(c, self); noop_visit_crate(c, self);
// Create a main function to run our tests // Create a main function to run our tests
c.module.items.push(mk_main(&mut self.cx)); c.items.push(mk_main(&mut self.cx));
} }
fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> { fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
@ -103,9 +103,9 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
// We don't want to recurse into anything other than mods, since // We don't want to recurse into anything other than mods, since
// mods or tests inside of functions will break things // mods or tests inside of functions will break things
if let ast::ItemKind::Mod(mut module) = 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_mod(&mut module, self); noop_visit_item_kind(&mut item.kind, self);
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() {
@ -113,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),
@ -126,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)]
} }

View file

@ -209,7 +209,7 @@ pub fn features(sess: &Session, mut krate: ast::Crate) -> (ast::Crate, Features)
None => { None => {
// The entire crate is unconfigured. // The entire crate is unconfigured.
krate.attrs = Vec::new(); krate.attrs = Vec::new();
krate.module.items = Vec::new(); krate.items = Vec::new();
Features::default() Features::default()
} }
Some(attrs) => { Some(attrs) => {

View file

@ -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};
@ -350,6 +350,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
MacroExpander { cx, monotonic } MacroExpander { cx, monotonic }
} }
// FIXME: Avoid visiting the crate as a `Mod` item,
// make crate a first class expansion target instead.
pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
let mut module = ModuleData { let mut module = ModuleData {
mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)], mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
@ -362,12 +364,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
self.cx.root_path = module.directory.clone(); self.cx.root_path = module.directory.clone();
self.cx.current_expansion.module = Rc::new(module); self.cx.current_expansion.module = Rc::new(module);
let orig_mod_span = krate.module.inner;
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(krate.module), kind: ast::ItemKind::Mod(
Unsafe::No,
ModKind::Loaded(krate.items, Inline::Yes, krate.span)
),
ident: Ident::invalid(), ident: Ident::invalid(),
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
vis: ast::Visibility { vis: ast::Visibility {
@ -379,28 +382,22 @@ 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.module = module; krate.items = items;
} }
None => { None => {
// Resolution failed so we return an empty expansion // Resolution failed so we return an empty expansion
krate.attrs = vec![]; krate.attrs = vec![];
krate.module = ast::Mod { krate.items = vec![];
inner: orig_mod_span,
unsafety: Unsafe::No,
items: vec![],
inline: true,
};
} }
Some(ast::Item { span, kind, .. }) => { Some(ast::Item { span, kind, .. }) => {
krate.attrs = vec![]; krate.attrs = vec![];
krate.module = ast::Mod { krate.items = vec![];
inner: orig_mod_span,
unsafety: Unsafe::No,
items: vec![],
inline: true,
};
self.cx.span_err( self.cx.span_err(
span, span,
&format!( &format!(
@ -814,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,
@ -1271,52 +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 (new_mod, dir) = parse_external_mod(
&self.cx.sess,
ident,
span,
old_mod.unsafety,
dir,
&mut attrs,
pushed,
);
let krate = ast::Crate {
span: new_mod.inner,
module: new_mod,
attrs,
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 = krate.module; 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.

View file

@ -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,26 +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 mut module = parser.parse_mod(&token::Eof, unsafety)?; let (mut inner_attrs, items, inner_span) = parser.parse_mod(&token::Eof)?;
module.0.inline = false; attrs.append(&mut inner_attrs);
module (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>(

View file

@ -7,8 +7,8 @@ use rustc_span::symbol::Ident;
use rustc_span::with_default_session_globals; use rustc_span::with_default_session_globals;
// This version doesn't care about getting comments or doc-strings in. // This version doesn't care about getting comments or doc-strings in.
fn fake_print_crate(s: &mut pprust::State<'_>, krate: &ast::Crate) { fn print_crate_items(krate: &ast::Crate) -> String {
s.print_mod(&krate.module, &krate.attrs) krate.items.iter().map(|i| pprust::item_to_string(i)).collect::<Vec<_>>().join(" ")
} }
// Change every identifier to "zz". // Change every identifier to "zz".
@ -46,7 +46,7 @@ fn ident_transformation() {
assert_pred!( assert_pred!(
matches_codepattern, matches_codepattern,
"matches_codepattern", "matches_codepattern",
pprust::to_string(|s| fake_print_crate(s, &krate)), print_crate_items(&krate),
"#[zz]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string() "#[zz]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string()
); );
}) })
@ -66,7 +66,7 @@ fn ident_transformation_in_defs() {
assert_pred!( assert_pred!(
matches_codepattern, matches_codepattern,
"matches_codepattern", "matches_codepattern",
pprust::to_string(|s| fake_print_crate(s, &krate)), print_crate_items(&krate),
"macro_rules! zz{(zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+))}".to_string() "macro_rules! zz{(zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+))}".to_string()
); );
}) })

View file

@ -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!();
} }

View file

@ -616,7 +616,7 @@ pub struct WhereEqPredicate<'hir> {
pub rhs_ty: &'hir Ty<'hir>, pub rhs_ty: &'hir Ty<'hir>,
} }
#[derive(Encodable, Debug, HashStable_Generic)] #[derive(Default, Encodable, Debug, HashStable_Generic)]
pub struct ModuleItems { pub struct ModuleItems {
// Use BTreeSets here so items are in the same order as in the // Use BTreeSets here so items are in the same order as in the
// list of all items in Crate // list of all items in Crate

View file

@ -188,13 +188,6 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
run_early_pass!(self, check_ident, ident); run_early_pass!(self, check_ident, ident);
} }
fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, _a: &[ast::Attribute], n: ast::NodeId) {
run_early_pass!(self, check_mod, m, s, n);
self.check_id(n);
ast_visit::walk_mod(self, m);
run_early_pass!(self, check_mod_post, m, s, n);
}
fn visit_local(&mut self, l: &'a ast::Local) { fn visit_local(&mut self, l: &'a ast::Local) {
self.with_lint_attrs(l.id, &l.attrs, |cx| { self.with_lint_attrs(l.id, &l.attrs, |cx| {
run_early_pass!(cx, check_local, l); run_early_pass!(cx, check_local, l);

View file

@ -160,8 +160,6 @@ macro_rules! early_lint_methods {
fn check_ident(a: Ident); fn check_ident(a: Ident);
fn check_crate(a: &ast::Crate); fn check_crate(a: &ast::Crate);
fn check_crate_post(a: &ast::Crate); fn check_crate_post(a: &ast::Crate);
fn check_mod(a: &ast::Mod, b: Span, c: ast::NodeId);
fn check_mod_post(a: &ast::Mod, b: Span, c: ast::NodeId);
fn check_foreign_item(a: &ast::ForeignItem); fn check_foreign_item(a: &ast::ForeignItem);
fn check_foreign_item_post(a: &ast::ForeignItem); fn check_foreign_item_post(a: &ast::ForeignItem);
fn check_item(a: &ast::Item); fn check_item(a: &ast::Item);

View file

@ -25,11 +25,9 @@ use tracing::debug;
impl<'a> Parser<'a> { impl<'a> Parser<'a> {
/// Parses a source module as a crate. This is the main entry point for the parser. /// Parses a source module as a crate. This is the main entry point for the parser.
pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> { pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
let lo = self.token.span; let (attrs, items, span) = self.parse_mod(&token::Eof)?;
let (module, attrs) = self.parse_mod(&token::Eof, Unsafe::No)?;
let span = lo.to(self.token.span);
let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`. let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`.
Ok(ast::Crate { attrs, module, span, proc_macros }) Ok(ast::Crate { attrs, items, span, proc_macros })
} }
/// Parses a `mod <foo> { ... }` or `mod <foo>;` item. /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
@ -37,35 +35,26 @@ 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 (module, mut inner_attrs) = if self.eat(&token::Semi) { let mod_kind = if self.eat(&token::Semi) {
(Mod { inner: Span::default(), unsafety, items: Vec::new(), inline: false }, Vec::new()) ModKind::Unloaded
} else { } else {
self.expect(&token::OpenDelim(token::Brace))?; self.expect(&token::OpenDelim(token::Brace))?;
self.parse_mod(&token::CloseDelim(token::Brace), unsafety)? 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(module)))
} }
/// Parses the contents of a module (inner attributes followed by module items). /// Parses the contents of a module (inner attributes followed by module items).
pub fn parse_mod( pub fn parse_mod(
&mut self, &mut self,
term: &TokenKind, term: &TokenKind,
unsafety: Unsafe, ) -> PResult<'a, (Vec<Attribute>, Vec<P<Item>>, Span)> {
) -> PResult<'a, (Mod, Vec<Attribute>)> {
let lo = self.token.span; let lo = self.token.span;
let attrs = self.parse_inner_attributes()?; let attrs = self.parse_inner_attributes()?;
let module = self.parse_mod_items(term, lo, unsafety)?;
Ok((module, attrs))
}
/// Given a termination token, parses all of the items in a module.
fn parse_mod_items(
&mut self,
term: &TokenKind,
inner_lo: Span,
unsafety: Unsafe,
) -> PResult<'a, Mod> {
let mut items = vec![]; let mut items = vec![];
while let Some(item) = self.parse_item(ForceCollect::No)? { while let Some(item) = self.parse_item(ForceCollect::No)? {
items.push(item); items.push(item);
@ -82,9 +71,7 @@ impl<'a> Parser<'a> {
} }
} }
let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span }; Ok((attrs, items, lo.to(self.prev_token.span)))
Ok(Mod { inner: inner_lo.to(hi), unsafety, items, inline: true })
} }
} }

View file

@ -124,11 +124,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
hir_visit::walk_item(self, i) hir_visit::walk_item(self, i)
} }
fn visit_mod(&mut self, m: &'v hir::Mod<'v>, _s: Span, n: hir::HirId) {
self.record("Mod", Id::None, m);
hir_visit::walk_mod(self, m, n)
}
fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem<'v>) { fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem<'v>) {
self.record("ForeignItem", Id::Node(i.hir_id()), i); self.record("ForeignItem", Id::Node(i.hir_id()), i);
hir_visit::walk_foreign_item(self, i) hir_visit::walk_foreign_item(self, i)
@ -252,11 +247,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
} }
impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
fn visit_mod(&mut self, m: &'v ast::Mod, _s: Span, _a: &[ast::Attribute], _n: NodeId) {
self.record("Mod", Id::None, m);
ast_visit::walk_mod(self, m)
}
fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) { fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) {
self.record("ForeignItem", Id::None, i); self.record("ForeignItem", Id::None, i);
ast_visit::walk_foreign_item(self, i) ast_visit::walk_foreign_item(self, i)

View file

@ -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);
}); });

View file

@ -11,6 +11,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(bool_to_option)] #![feature(bool_to_option)]
#![feature(control_flow_enum)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(format_args_capture)] #![feature(format_args_capture)]
#![feature(nll)] #![feature(nll)]
@ -23,11 +24,12 @@ use Determinacy::*;
use rustc_arena::{DroplessArena, TypedArena}; use rustc_arena::{DroplessArena, TypedArena};
use rustc_ast::node_id::NodeMap; use rustc_ast::node_id::NodeMap;
use rustc_ast::ptr::P;
use rustc_ast::unwrap_or; 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};
@ -59,6 +61,7 @@ use rustc_span::{Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::ops::ControlFlow;
use std::{cmp, fmt, iter, ptr}; use std::{cmp, fmt, iter, ptr};
use tracing::debug; use tracing::debug;
@ -283,28 +286,21 @@ struct UsePlacementFinder {
impl UsePlacementFinder { impl UsePlacementFinder {
fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, bool) { fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, bool) {
let mut finder = UsePlacementFinder { target_module, span: None, found_use: false }; let mut finder = UsePlacementFinder { target_module, span: None, found_use: false };
visit::walk_crate(&mut finder, krate); if let ControlFlow::Continue(..) = finder.check_mod(&krate.items, CRATE_NODE_ID) {
visit::walk_crate(&mut finder, krate);
}
(finder.span, finder.found_use) (finder.span, finder.found_use)
} }
}
impl<'tcx> Visitor<'tcx> for UsePlacementFinder { fn check_mod(&mut self, items: &[P<ast::Item>], node_id: NodeId) -> ControlFlow<()> {
fn visit_mod(
&mut self,
module: &'tcx ast::Mod,
_: Span,
_: &[ast::Attribute],
node_id: NodeId,
) {
if self.span.is_some() { if self.span.is_some() {
return; return ControlFlow::Break(());
} }
if node_id != self.target_module { if node_id != self.target_module {
visit::walk_mod(self, module); return ControlFlow::Continue(());
return;
} }
// find a use statement // find a use statement
for item in &module.items { for item in items {
match item.kind { match item.kind {
ItemKind::Use(..) => { ItemKind::Use(..) => {
// don't suggest placing a use before the prelude // don't suggest placing a use before the prelude
@ -312,7 +308,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
if !item.span.from_expansion() { if !item.span.from_expansion() {
self.span = Some(item.span.shrink_to_lo()); self.span = Some(item.span.shrink_to_lo());
self.found_use = true; self.found_use = true;
return; return ControlFlow::Break(());
} }
} }
// don't place use before extern crate // don't place use before extern crate
@ -337,6 +333,18 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
} }
} }
} }
ControlFlow::Continue(())
}
}
impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
fn visit_item(&mut self, item: &'tcx ast::Item) {
if let ItemKind::Mod(_, ModKind::Loaded(items, ..)) = &item.kind {
if let ControlFlow::Break(..) = self.check_mod(items, item.id) {
return;
}
}
visit::walk_item(self, item);
} }
} }

View file

@ -1 +1 @@
{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} {"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0},"proc_macros":[]}

View file

@ -1 +1 @@
{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} {"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0},"proc_macros":[]}

View file

@ -7,10 +7,8 @@ LL | #![allow(unused_variables)];
error[E0601]: `main` function not found in crate `issue_49040` error[E0601]: `main` function not found in crate `issue_49040`
--> $DIR/issue-49040.rs:1:1 --> $DIR/issue-49040.rs:1:1
| |
LL | / #![allow(unused_variables)]; LL | #![allow(unused_variables)];
LL | | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/issue-49040.rs`
LL | | fn foo() {}
| |__^ consider adding a `main` function to `$DIR/issue-49040.rs`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -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))