diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index cd0ad2b0150..3550055ac10 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -486,8 +486,8 @@ pub struct WhereEqPredicate { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Crate { - pub module: Mod, pub attrs: Vec, + pub items: Vec>, pub span: Span, /// The order of items in the HIR is unrelated to the order of /// items in the AST. However, we generate proc macro harnesses @@ -2299,21 +2299,22 @@ pub fn span(&self) -> Span { } } -/// Module declaration. -/// -/// E.g., `mod foo;` or `mod foo { .. }`. +#[derive(Clone, PartialEq, Encodable, Decodable, Debug)] +pub enum Inline { + Yes, + No, +} + +/// Module item kind. #[derive(Clone, Encodable, Decodable, Debug)] -pub struct Mod { - /// A span from the first token past `{` to the last token until `}`. - /// For `mod foo;`, the inner span ranges from the first token - /// to the last token in the external file. - pub inner: Span, - /// `unsafe` keyword accepted syntactically for macro DSLs, but not - /// semantically by Rust. - pub unsafety: Unsafe, - pub items: Vec>, - /// `true` for `mod foo { .. }`; `false` for `mod foo;`. - pub inline: bool, +pub enum ModKind { + /// Module with inlined definition `mod foo { ... }`, + /// or with definition outlined to a separate file `mod foo;` and already loaded from it. + /// The inner span is from the first token past `{` to the last token until `}`, + /// or from the first to the last token in the loaded file. + Loaded(Vec>, Inline, Span), + /// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it. + Unloaded, } /// Foreign module declaration. @@ -2710,7 +2711,9 @@ pub enum ItemKind { /// A module declaration (`mod`). /// /// 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`). /// /// E.g., `extern {}` or `extern "C" {}`. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 024d9687f31..c286738811c 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -170,10 +170,6 @@ fn visit_ty_constraint(&mut self, t: &mut AssocTyConstraint) { 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) { noop_visit_foreign_mod(nm, self); } @@ -917,7 +913,13 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { vis.visit_generics(generics); 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::GlobalAsm(_ga) => {} ItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => { @@ -998,14 +1000,10 @@ pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { vis.visit_asyncness(asyncness); } -pub fn noop_visit_mod(module: &mut Mod, vis: &mut T) { - let Mod { inner, unsafety: _, items, inline: _ } = module; - vis.visit_span(inner); - items.flat_map_in_place(|item| vis.flat_map_item(item)); -} - +// FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible, +// or make crate visiting first class if necessary. pub fn noop_visit_crate(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 = Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None }; let item = P(Item { @@ -1014,19 +1012,20 @@ pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { id: DUMMY_NODE_ID, vis: item_vis, span, - kind: ItemKind::Mod(module), + kind: ItemKind::Mod(Unsafe::No, ModKind::Loaded(items, Inline::Yes, span)), tokens: None, }); let items = vis.flat_map_item(item); let len = items.len(); if len == 0 { - let module = Mod { inner: span, unsafety: Unsafe::No, items: vec![], inline: true }; - Crate { module, attrs: vec![], span, proc_macros } + Crate { attrs: vec![], items: vec![], span, proc_macros } } else if len == 1 { let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner(); 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"), } } else { diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index c37d4cd9f79..32b9dd46bae 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -74,7 +74,7 @@ pub fn ctxt(&self) -> Option { /// Each method of the `Visitor` trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// 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 /// explicitly, you need to override each method. (And you also need @@ -87,9 +87,6 @@ fn visit_name(&mut self, _span: Span, _name: Symbol) { fn visit_ident(&mut self, ident: 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) { 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) { - 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); } -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) { for attr in local.attrs.iter() { 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()); 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) => { walk_list!(visitor, visit_foreign_item, &foreign_module.items); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index cad2a21d1a4..8b740b77740 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -15,11 +15,11 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; use rustc_target::spec::abi; - use smallvec::{smallvec, SmallVec}; -use std::collections::BTreeSet; use tracing::debug; +use std::mem; + pub(super) struct ItemLowerer<'a, 'lowering, 'hir> { pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>, } @@ -34,25 +34,6 @@ fn with_trait_impl_ref(&mut self, impl_ref: &Option, f: impl FnOnce(&m } 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) { let mut item_hir_id = None; self.lctx.with_hir_id_owner(item.id, |lctx| { @@ -67,10 +48,18 @@ fn visit_item(&mut self, item: &'a Item) { if let Some(hir_id) = item_hir_id { self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { let this = &mut ItemLowerer { lctx: this }; - if let ItemKind::Impl(box ImplKind { ref of_trait, .. }) = item.kind { - this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item)); - } else { - visit::walk_item(this, item); + match item.kind { + ItemKind::Mod(..) => { + let def_id = this.lctx.lower_node_id(item.id).expect_owner(); + 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 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { let hir_item = lctx.lower_trait_item(item); let id = hir_item.trait_item_id(); 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 => { let hir_item = lctx.lower_impl_item(item); let id = hir_item.impl_item_id(); 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 @@ fn visit_foreign_item(&mut self, item: &'a ForeignItem) { let hir_item = lctx.lower_foreign_item(item); let id = hir_item.foreign_item_id(); 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); @@ -157,7 +146,7 @@ fn without_in_scope_lifetime_defs( &mut self, f: impl FnOnce(&mut LoweringContext<'_, '_>) -> 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, // input types, and the like, and should not be non-empty in @@ -172,12 +161,10 @@ fn without_in_scope_lifetime_defs( res } - pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod<'hir> { + pub(super) fn lower_mod(&mut self, items: &[P], inner: Span) -> hir::Mod<'hir> { hir::Mod { - inner: m.inner, - item_ids: self - .arena - .alloc_from_iter(m.items.iter().flat_map(|x| self.lower_item_id(x))), + inner, + item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_id(x))), } } @@ -327,7 +314,12 @@ fn lower_item_kind( 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) => { if fm.abi.is_none() { self.maybe_lint_missing_abi(span, id, abi::Abi::C); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9d0b2cd5c67..05b417effd4 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -560,7 +560,7 @@ fn visit_ty(&mut self, t: &'tcx Ty) { visit::walk_crate(&mut MiscCollector { 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 body_ids = body_ids(&self.bodies); let proc_macros = @@ -608,7 +608,7 @@ fn visit_ty(&mut self, t: &'tcx Ty) { fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId { let id = hir::ItemId { def_id: item.def_id }; 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 } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 8defd91c688..563bcda5190 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1054,12 +1054,14 @@ fn visit_item(&mut self, item: &'a Item) { walk_list!(self, visit_attribute, &item.attrs); return; } - ItemKind::Mod(Mod { inline, unsafety, .. }) => { + ItemKind::Mod(unsafety, ref mod_kind) => { if let Unsafe::Yes(span) = unsafety { self.err_handler().span_err(span, "module cannot be declared unsafe"); } // 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); } } diff --git a/compiler/rustc_ast_passes/src/node_count.rs b/compiler/rustc_ast_passes/src/node_count.rs index 2971fa435c8..fb7e0d3450f 100644 --- a/compiler/rustc_ast_passes/src/node_count.rs +++ b/compiler/rustc_ast_passes/src/node_count.rs @@ -20,10 +20,6 @@ fn visit_ident(&mut self, ident: Ident) { self.count += 1; 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) { self.count += 1; walk_foreign_item(self, i) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 7f712643d19..82f6e936b76 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -9,7 +9,7 @@ use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle}; use rustc_ast::util::parser::{self, AssocOp, Fixity}; 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::{InlineAsmOperand, InlineAsmRegOrRegClass}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; @@ -87,7 +87,6 @@ pub struct State<'a> { pub s: pp::Printer, comments: Option>, ann: &'a (dyn PpAnn + 'a), - is_expanded: bool, } crate const INDENT_UNIT: usize = 4; @@ -103,12 +102,8 @@ pub fn print_crate<'a>( is_expanded: bool, edition: Edition, ) -> String { - let mut s = State { - s: pp::mk_printer(), - comments: Some(Comments::new(sm, filename, input)), - ann, - is_expanded, - }; + let mut s = + State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann }; 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 @@ -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.ann.post(&mut s, AnnNode::Crate(krate)); s.s.eof() @@ -853,7 +851,7 @@ fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: impl<'a> 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 @@ -891,13 +889,6 @@ pub fn synth_comment(&mut self, text: String) { 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]) { self.print_inner_attributes(attrs); for item in &nmod.items { @@ -1139,23 +1130,29 @@ fn print_associated_type( let body = body.as_deref(); 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| { s.print_visibility(&item.vis); - s.print_unsafety(_mod.unsafety); + s.print_unsafety(unsafety); s.word("mod"); })); self.print_ident(item.ident); - if _mod.inline || self.is_expanded { - self.nbsp(); - self.bopen(); - self.print_mod(_mod, &item.attrs); - self.bclose(item.span); - } else { - self.s.word(";"); - self.end(); // end inner head-block - self.end(); // end outer head-block + match mod_kind { + ModKind::Loaded(items, ..) => { + self.nbsp(); + self.bopen(); + self.print_inner_attributes(&item.attrs); + 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 + } } } ast::ItemKind::ForeignMod(ref nmod) => { diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 7582d980539..71bbae1161b 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -91,7 +91,7 @@ pub fn inject( } let decls = mk_decls(&mut krate, &mut cx, ¯os); - krate.module.items.push(decls); + krate.items.push(decls); krate } diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 91566ec1ef2..3a81d076dc5 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -44,7 +44,7 @@ pub fn inject( // .rev() to preserve ordering above in combination with insert(0, ...) for &name in names.iter().rev() { let ident = if rust_2018 { Ident::new(name, span) } else { Ident::new(name, call_site) }; - krate.module.items.insert( + krate.items.insert( 0, cx.item( span, @@ -79,7 +79,7 @@ pub fn inject( })), ); - krate.module.items.insert(0, use_item); + krate.items.insert(0, use_item); krate } diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 4ac22be3c27..28e82597843 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -1,10 +1,10 @@ // Code that generates a test runner to run all the tests in a crate use rustc_ast as ast; -use rustc_ast::attr; use rustc_ast::entry::EntryPointType; use rustc_ast::mut_visit::{ExpectOne, *}; use rustc_ast::ptr::P; +use rustc_ast::{attr, ModKind}; use rustc_expand::base::{ExtCtxt, ResolverExpand}; use rustc_expand::expand::{AstFragment, ExpansionConfig}; use rustc_feature::Features; @@ -89,7 +89,7 @@ fn visit_crate(&mut self, c: &mut ast::Crate) { noop_visit_crate(c, self); // 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) -> SmallVec<[P; 1]> { @@ -103,9 +103,9 @@ fn visit_crate(&mut self, c: &mut ast::Crate) { // We don't want to recurse into anything other than mods, since // 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); - noop_visit_mod(&mut module, self); + noop_visit_item_kind(&mut item.kind, self); let mut tests = mem::replace(&mut self.tests, tests); if !tests.is_empty() { @@ -113,8 +113,12 @@ fn visit_crate(&mut self, c: &mut ast::Crate) { if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id }; // Create an identifier that will hygienically resolve the test // 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( - module.inner, + inner_span, AstPass::TestHarness, &[], Some(parent), @@ -126,7 +130,6 @@ fn visit_crate(&mut self, c: &mut ast::Crate) { } self.cx.test_cases.extend(tests); } - item.kind = ast::ItemKind::Mod(module); } smallvec![P(item)] } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index b07bce94870..ad04fa9a958 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -209,7 +209,7 @@ pub fn features(sess: &Session, mut krate: ast::Crate) -> (ast::Crate, Features) None => { // The entire crate is unconfigured. krate.attrs = Vec::new(); - krate.module.items = Vec::new(); + krate.items = Vec::new(); Features::default() } Some(attrs) => { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index f23e3b9f747..5a4737842f0 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -12,8 +12,8 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; -use rustc_ast::{AttrItem, AttrStyle, Block, ItemKind, LitKind, MacArgs}; -use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, NestedMetaItem}; +use rustc_ast::{AttrItem, AttrStyle, Block, Inline, ItemKind, LitKind, MacArgs}; +use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem}; use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; @@ -350,6 +350,8 @@ pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self { 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 { let mut module = ModuleData { mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)], @@ -362,12 +364,13 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { self.cx.root_path = module.directory.clone(); self.cx.current_expansion.module = Rc::new(module); - let orig_mod_span = krate.module.inner; - let krate_item = AstFragment::Items(smallvec![P(ast::Item { attrs: krate.attrs, 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(), id: ast::DUMMY_NODE_ID, vis: ast::Visibility { @@ -379,28 +382,22 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { })]); 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.module = module; + krate.items = items; } None => { // Resolution failed so we return an empty expansion krate.attrs = vec![]; - krate.module = ast::Mod { - inner: orig_mod_span, - unsafety: Unsafe::No, - items: vec![], - inline: true, - }; + krate.items = vec![]; } Some(ast::Item { span, kind, .. }) => { krate.attrs = vec![]; - krate.module = ast::Mod { - inner: orig_mod_span, - unsafety: Unsafe::No, - items: vec![], - inline: true, - }; + krate.items = vec![]; self.cx.span_err( span, &format!( @@ -814,7 +811,9 @@ struct GateProcMacroInput<'a> { impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> { fn visit_item(&mut self, item: &'ast ast::Item) { 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( self.parse_sess, sym::proc_macro_hygiene, @@ -1271,52 +1270,47 @@ fn visit_block(&mut self, block: &mut P) { _ => 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 orig_ownership = self.cx.current_expansion.directory_ownership; let mut module = (*self.cx.current_expansion.module).clone(); let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop. let dir = Directory { ownership: orig_ownership, path: module.directory }; - let Directory { ownership, path } = if old_mod.inline { - // Inline `mod foo { ... }`, but we still need to push directories. - item.attrs = attrs; - push_directory(&self.cx.sess, ident, &item.attrs, dir) - } else { - // 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); + let Directory { ownership, path } = match mod_kind { + ModKind::Loaded(_, Inline::Yes, _) => { + // Inline `mod foo { ... }`, but we still need to push directories. + item.attrs = attrs; + push_directory(&self.cx.sess, ident, &item.attrs, dir) } + 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; - 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(); + let krate = + ast::Crate { attrs, items, span: inner_span, proc_macros: vec![] }; + if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded { + extern_mod_loaded(&krate, ident); } - }; - 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. diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 171cb3fa8e6..076d3b02be9 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -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_parse::new_parser_from_file; use rustc_session::parse::ParseSess; @@ -42,11 +43,10 @@ pub struct ModulePathSuccess { sess: &Session, id: Ident, span: Span, // The span to blame on errors. - unsafety: Unsafe, Directory { mut ownership, path }: Directory, attrs: &mut Vec, pop_mod_stack: &mut bool, -) -> (Mod, Directory) { +) -> (Vec>, Span, Directory) { // We bail on the first error, but that error does not cause a fatal error... (1) let result: PResult<'_, _> = try { // Extract the file path and the new ownership. @@ -62,26 +62,22 @@ pub struct ModulePathSuccess { // Actually parse the external file as a module. let mut parser = new_parser_from_file(&sess.parse_sess, &mp.path, Some(span)); - let mut module = parser.parse_mod(&token::Eof, unsafety)?; - module.0.inline = false; - module + let (mut inner_attrs, items, inner_span) = parser.parse_mod(&token::Eof)?; + attrs.append(&mut inner_attrs); + (items, inner_span) }; // (1) ...instead, we return a dummy module. - let (module, mut new_attrs) = result.map_err(|mut err| err.emit()).unwrap_or_else(|_| { - let module = Mod { inner: Span::default(), unsafety, items: Vec::new(), inline: false }; - (module, Vec::new()) - }); - attrs.append(&mut new_attrs); + let (items, inner_span) = result.map_err(|mut err| err.emit()).unwrap_or_default(); - // Extract the directory path for submodules of `module`. - let path = sess.source_map().span_to_unmapped_path(module.inner); + // Extract the directory path for submodules of the module. + let path = sess.source_map().span_to_unmapped_path(inner_span); let mut path = match path { FileName::Real(name) => name.into_local_path(), other => PathBuf::from(other.to_string()), }; path.pop(); - (module, Directory { ownership, path }) + (items, inner_span, Directory { ownership, path }) } fn error_on_circular_module<'a>( diff --git a/compiler/rustc_expand/src/mut_visit/tests.rs b/compiler/rustc_expand/src/mut_visit/tests.rs index be0300bad98..7e7155ad278 100644 --- a/compiler/rustc_expand/src/mut_visit/tests.rs +++ b/compiler/rustc_expand/src/mut_visit/tests.rs @@ -7,8 +7,8 @@ use rustc_span::with_default_session_globals; // This version doesn't care about getting comments or doc-strings in. -fn fake_print_crate(s: &mut pprust::State<'_>, krate: &ast::Crate) { - s.print_mod(&krate.module, &krate.attrs) +fn print_crate_items(krate: &ast::Crate) -> String { + krate.items.iter().map(|i| pprust::item_to_string(i)).collect::>().join(" ") } // Change every identifier to "zz". @@ -46,7 +46,7 @@ fn ident_transformation() { assert_pred!( 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() ); }) @@ -66,7 +66,7 @@ fn ident_transformation_in_defs() { assert_pred!( 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() ); }) diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs index f4fcaf5c0a4..56f25ffdb01 100644 --- a/compiler/rustc_expand/src/parse/tests.rs +++ b/compiler/rustc_expand/src/parse/tests.rs @@ -309,8 +309,8 @@ fn out_of_line_mod() { .unwrap() .unwrap(); - if let ast::ItemKind::Mod(ref m) = item.kind { - assert!(m.items.len() == 2); + if let ast::ItemKind::Mod(_, ref mod_kind) = item.kind { + assert!(matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2)); } else { panic!(); } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 59b7266ce48..4df8c44e62b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -616,7 +616,7 @@ pub struct WhereEqPredicate<'hir> { pub rhs_ty: &'hir Ty<'hir>, } -#[derive(Encodable, Debug, HashStable_Generic)] +#[derive(Default, Encodable, Debug, HashStable_Generic)] pub struct ModuleItems { // Use BTreeSets here so items are in the same order as in the // list of all items in Crate diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 231edf442eb..cc3bf4095fd 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -188,13 +188,6 @@ fn visit_ident(&mut self, 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) { self.with_lint_attrs(l.id, &l.attrs, |cx| { run_early_pass!(cx, check_local, l); diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 828f283d2a9..ffbed3a0aff 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -160,8 +160,6 @@ macro_rules! early_lint_methods { fn check_ident(a: Ident); fn check_crate(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_post(a: &ast::ForeignItem); fn check_item(a: &ast::Item); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index cdea82f50ed..0f907859a19 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -25,11 +25,9 @@ impl<'a> Parser<'a> { /// 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> { - let lo = self.token.span; - let (module, attrs) = self.parse_mod(&token::Eof, Unsafe::No)?; - let span = lo.to(self.token.span); + let (attrs, items, span) = self.parse_mod(&token::Eof)?; 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 { ... }` or `mod ;` item. @@ -37,35 +35,26 @@ fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Mod)?; let id = self.parse_ident()?; - let (module, mut inner_attrs) = if self.eat(&token::Semi) { - (Mod { inner: Span::default(), unsafety, items: Vec::new(), inline: false }, Vec::new()) + let mod_kind = if self.eat(&token::Semi) { + ModKind::Unloaded } else { 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(module))) + Ok((id, ItemKind::Mod(unsafety, mod_kind))) } /// Parses the contents of a module (inner attributes followed by module items). pub fn parse_mod( &mut self, term: &TokenKind, - unsafety: Unsafe, - ) -> PResult<'a, (Mod, Vec)> { + ) -> PResult<'a, (Vec, Vec>, Span)> { let lo = self.token.span; 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![]; while let Some(item) = self.parse_item(ForceCollect::No)? { items.push(item); @@ -82,9 +71,7 @@ fn parse_mod_items( } } - let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span }; - - Ok(Mod { inner: inner_lo.to(hi), unsafety, items, inline: true }) + Ok((attrs, items, lo.to(self.prev_token.span))) } } diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 8d5a5bdf6b7..fac28281593 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -124,11 +124,6 @@ fn visit_item(&mut self, i: &'v hir::Item<'v>) { 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>) { self.record("ForeignItem", Id::Node(i.hir_id()), i); hir_visit::walk_foreign_item(self, i) @@ -252,11 +247,6 @@ fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef<'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) { self.record("ForeignItem", Id::None, i); ast_visit::walk_foreign_item(self, i) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index cca40a793dd..09ab84eaeb6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1023,7 +1023,7 @@ fn resolve_item(&mut self, item: &'ast Item) { }); } - ItemKind::Mod(_) | ItemKind::ForeignMod(_) => { + ItemKind::Mod(..) | ItemKind::ForeignMod(_) => { self.with_scope(item.id, |this| { visit::walk_item(this, item); }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index bca3c7b1b03..77fbbaa1532 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -11,6 +11,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] #![feature(bool_to_option)] +#![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(format_args_capture)] #![feature(nll)] @@ -23,11 +24,12 @@ use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::node_id::NodeMap; +use rustc_ast::ptr::P; use rustc_ast::unwrap_or; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, NodeId}; 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_pretty::pprust; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; @@ -59,6 +61,7 @@ use smallvec::{smallvec, SmallVec}; use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; +use std::ops::ControlFlow; use std::{cmp, fmt, iter, ptr}; use tracing::debug; @@ -283,28 +286,21 @@ struct UsePlacementFinder { impl UsePlacementFinder { fn check(krate: &Crate, target_module: NodeId) -> (Option, bool) { 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) } -} -impl<'tcx> Visitor<'tcx> for UsePlacementFinder { - fn visit_mod( - &mut self, - module: &'tcx ast::Mod, - _: Span, - _: &[ast::Attribute], - node_id: NodeId, - ) { + fn check_mod(&mut self, items: &[P], node_id: NodeId) -> ControlFlow<()> { if self.span.is_some() { - return; + return ControlFlow::Break(()); } if node_id != self.target_module { - visit::walk_mod(self, module); - return; + return ControlFlow::Continue(()); } // find a use statement - for item in &module.items { + for item in items { match item.kind { ItemKind::Use(..) => { // don't suggest placing a use before the prelude @@ -312,7 +308,7 @@ fn visit_mod( if !item.span.from_expansion() { self.span = Some(item.span.shrink_to_lo()); self.found_use = true; - return; + return ControlFlow::Break(()); } } // don't place use before extern crate @@ -337,6 +333,18 @@ fn visit_mod( } } } + 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); } } diff --git a/src/test/ui/ast-json/ast-json-noexpand-output.stdout b/src/test/ui/ast-json/ast-json-noexpand-output.stdout index 02342af8dc5..0307875c154 100644 --- a/src/test/ui/ast-json/ast-json-noexpand-output.stdout +++ b/src/test/ui/ast-json/ast-json-noexpand-output.stdout @@ -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":[]} diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index 235f39c567b..d26530efe3e 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -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":[]} diff --git a/src/test/ui/issues/issue-49040.stderr b/src/test/ui/issues/issue-49040.stderr index 4134d6aa544..56befe3a0a7 100644 --- a/src/test/ui/issues/issue-49040.stderr +++ b/src/test/ui/issues/issue-49040.stderr @@ -7,10 +7,8 @@ LL | #![allow(unused_variables)]; error[E0601]: `main` function not found in crate `issue_49040` --> $DIR/issue-49040.rs:1:1 | -LL | / #![allow(unused_variables)]; -LL | | -LL | | fn foo() {} - | |__^ consider adding a `main` function to `$DIR/issue-49040.rs` +LL | #![allow(unused_variables)]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/issue-49040.rs` error: aborting due to 2 previous errors diff --git a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs index 64232646972..9ff7ef7cc3b 100644 --- a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs +++ b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs @@ -241,9 +241,12 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r)) } - (Mod(l), Mod(r)) => { - l.inline == r.inline && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_item_kind)) - } + (Mod(lu, lmk), Mod(ru, rmk)) => lu == ru && match (lmk, rmk) { + (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)) => { 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))