about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/formatting.rs2
-rw-r--r--src/items.rs4
-rw-r--r--src/modules.rs159
-rw-r--r--src/syntux/parser.rs6
-rw-r--r--src/visitor.rs29
5 files changed, 130 insertions, 70 deletions
diff --git a/src/formatting.rs b/src/formatting.rs
index e42864a5055..2c38de04797 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -145,7 +145,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
         module: &Module<'_>,
         is_macro_def: bool,
     ) -> Result<(), ErrorKind> {
-        let snippet_provider = self.parse_session.snippet_provider(module.as_ref().inner);
+        let snippet_provider = self.parse_session.snippet_provider(module.span);
         let mut visitor = FmtVisitor::from_parse_sess(
             &self.parse_session,
             &self.config,
diff --git a/src/items.rs b/src/items.rs
index 6cdbb686ad8..00757210ce5 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -3271,8 +3271,8 @@ pub(crate) fn rewrite_extern_crate(
 /// Returns `true` for `mod foo;`, false for `mod foo { .. }`.
 pub(crate) fn is_mod_decl(item: &ast::Item) -> bool {
     match item.kind {
-        ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(),
-        _ => false,
+        ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _)) => false,
+        _ => true,
     }
 }
 
diff --git a/src/modules.rs b/src/modules.rs
index eaa889bcb3f..2ee3639ffb1 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -6,6 +6,7 @@ use rustc_ast::ast;
 use rustc_ast::attr::HasAttrs;
 use rustc_ast::visit::Visitor;
 use rustc_span::symbol::{self, sym, Symbol};
+use rustc_span::Span;
 use thiserror::Error;
 
 use crate::attr::MetaVisitor;
@@ -24,20 +25,31 @@ type FileModMap<'ast> = BTreeMap<FileName, Module<'ast>>;
 /// Represents module with its inner attributes.
 #[derive(Debug, Clone)]
 pub(crate) struct Module<'a> {
-    ast_mod: Cow<'a, ast::Mod>,
+    ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
+    pub(crate) items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
+    attrs: Cow<'a, Vec<ast::Attribute>>,
     inner_attr: Vec<ast::Attribute>,
+    pub(crate) span: Span,
 }
 
 impl<'a> Module<'a> {
-    pub(crate) fn new(ast_mod: Cow<'a, ast::Mod>, attrs: &[ast::Attribute]) -> Self {
-        let inner_attr = attrs
+    pub(crate) fn new(
+        mod_span: Span,
+        ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
+        mod_items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
+        mod_attrs: Cow<'a, Vec<ast::Attribute>>,
+    ) -> Self {
+        let inner_attr = mod_attrs
             .iter()
             .filter(|attr| attr.style == ast::AttrStyle::Inner)
             .cloned()
             .collect();
         Module {
-            ast_mod,
+            items: mod_items,
+            attrs: mod_attrs,
             inner_attr,
+            span: mod_span,
+            ast_mod_kind,
         }
     }
 }
@@ -51,12 +63,6 @@ impl<'a> HasAttrs for Module<'a> {
     }
 }
 
-impl<'a> AsRef<ast::Mod> for Module<'a> {
-    fn as_ref(&self) -> &ast::Mod {
-        &self.ast_mod
-    }
-}
-
 /// Maps each module to the corresponding file.
 pub(crate) struct ModResolver<'ast, 'sess> {
     parse_sess: &'sess ParseSess,
@@ -124,12 +130,17 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
 
         // Skip visiting sub modules when the input is from stdin.
         if self.recursive {
-            self.visit_mod_from_ast(&krate.module)?;
+            self.visit_mod_from_ast(&krate.items)?;
         }
 
         self.file_map.insert(
             root_filename,
-            Module::new(Cow::Borrowed(&krate.module), &krate.attrs),
+            Module::new(
+                krate.span,
+                None,
+                Cow::Borrowed(&krate.items),
+                Cow::Borrowed(&krate.attrs),
+            ),
         );
         Ok(self.file_map)
     }
@@ -139,10 +150,15 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
         let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess);
         visitor.visit_item(&item);
         for module_item in visitor.mods() {
-            if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.kind {
+            if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind {
                 self.visit_sub_mod(
                     &module_item.item,
-                    Module::new(Cow::Owned(sub_mod.clone()), &module_item.item.attrs),
+                    Module::new(
+                        module_item.item.span,
+                        Some(Cow::Owned(sub_mod_kind.clone())),
+                        Cow::Owned(vec![]),
+                        Cow::Owned(vec![]),
+                    ),
                 )?;
             }
         }
@@ -150,29 +166,53 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
     }
 
     /// Visit modules defined inside macro calls.
-    fn visit_mod_outside_ast(&mut self, module: ast::Mod) -> Result<(), ModuleResolutionError> {
-        for item in module.items {
+    fn visit_mod_outside_ast(
+        &mut self,
+        items: Vec<rustc_ast::ptr::P<ast::Item>>,
+    ) -> Result<(), ModuleResolutionError> {
+        for item in items {
             if is_cfg_if(&item) {
                 self.visit_cfg_if(Cow::Owned(item.into_inner()))?;
                 continue;
             }
 
-            if let ast::ItemKind::Mod(ref sub_mod) = item.kind {
-                self.visit_sub_mod(&item, Module::new(Cow::Owned(sub_mod.clone()), &item.attrs))?;
+            if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind {
+                let span = item.span;
+                self.visit_sub_mod(
+                    &item,
+                    Module::new(
+                        span,
+                        Some(Cow::Owned(sub_mod_kind.clone())),
+                        Cow::Owned(vec![]),
+                        Cow::Owned(vec![]),
+                    ),
+                )?;
             }
         }
         Ok(())
     }
 
     /// Visit modules from AST.
-    fn visit_mod_from_ast(&mut self, module: &'ast ast::Mod) -> Result<(), ModuleResolutionError> {
-        for item in &module.items {
+    fn visit_mod_from_ast(
+        &mut self,
+        items: &'ast Vec<rustc_ast::ptr::P<ast::Item>>,
+    ) -> Result<(), ModuleResolutionError> {
+        for item in items {
             if is_cfg_if(item) {
                 self.visit_cfg_if(Cow::Borrowed(item))?;
             }
 
-            if let ast::ItemKind::Mod(ref sub_mod) = item.kind {
-                self.visit_sub_mod(item, Module::new(Cow::Borrowed(sub_mod), &item.attrs))?;
+            if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind {
+                let span = item.span;
+                self.visit_sub_mod(
+                    item,
+                    Module::new(
+                        span,
+                        Some(Cow::Borrowed(sub_mod_kind)),
+                        Cow::Owned(vec![]),
+                        Cow::Borrowed(&item.attrs),
+                    ),
+                )?;
             }
         }
         Ok(())
@@ -273,9 +313,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
         if let Some(directory) = directory {
             self.directory = directory;
         }
-        match sub_mod.ast_mod {
-            Cow::Borrowed(sub_mod) => self.visit_mod_from_ast(sub_mod),
-            Cow::Owned(sub_mod) => self.visit_mod_outside_ast(sub_mod),
+        match (sub_mod.ast_mod_kind, sub_mod.items) {
+            (Some(Cow::Borrowed(ast::ModKind::Loaded(items, ast::Inline::No, _))), _) => {
+                self.visit_mod_from_ast(&items)
+            }
+            (Some(Cow::Owned(..)), Cow::Owned(items)) => self.visit_mod_outside_ast(items),
+            (_, _) => Ok(()),
         }
     }
 
@@ -294,13 +337,17 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
             if self.parse_sess.is_file_parsed(&path) {
                 return Ok(None);
             }
-            return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.ast_mod.inner)
-            {
-                Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None),
-                Ok(m) => Ok(Some(SubModKind::External(
+            return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.span) {
+                Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None),
+                Ok((attrs, items, span)) => Ok(Some(SubModKind::External(
                     path,
                     DirectoryOwnership::Owned { relative: None },
-                    Module::new(Cow::Owned(m.0), &m.1),
+                    Module::new(
+                        span,
+                        Some(Cow::Owned(ast::ModKind::Unloaded)),
+                        Cow::Owned(items),
+                        Cow::Owned(attrs),
+                    ),
                 ))),
                 Err(ParserError::ParseError) => Err(ModuleResolutionError {
                     module: mod_name.to_string(),
@@ -338,18 +385,30 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                         return Ok(Some(SubModKind::MultiExternal(mods_outside_ast)));
                     }
                 }
-                match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.ast_mod.inner) {
-                    Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None),
-                    Ok(m) if outside_mods_empty => Ok(Some(SubModKind::External(
-                        path,
-                        ownership,
-                        Module::new(Cow::Owned(m.0), &m.1),
-                    ))),
-                    Ok(m) => {
+                match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.span) {
+                    Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None),
+                    Ok((attrs, items, span)) if outside_mods_empty => {
+                        Ok(Some(SubModKind::External(
+                            path,
+                            ownership,
+                            Module::new(
+                                span,
+                                Some(Cow::Owned(ast::ModKind::Unloaded)),
+                                Cow::Owned(items),
+                                Cow::Owned(attrs),
+                            ),
+                        )))
+                    }
+                    Ok((attrs, items, span)) => {
                         mods_outside_ast.push((
                             path.clone(),
                             ownership,
-                            Module::new(Cow::Owned(m.0), &m.1),
+                            Module::new(
+                                span,
+                                Some(Cow::Owned(ast::ModKind::Unloaded)),
+                                Cow::Owned(items),
+                                Cow::Owned(attrs),
+                            ),
                         ));
                         if should_insert {
                             mods_outside_ast.push((path, ownership, sub_mod.clone()));
@@ -437,20 +496,22 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                 ));
                 continue;
             }
-            let m = match Parser::parse_file_as_module(
-                self.parse_sess,
-                &actual_path,
-                sub_mod.ast_mod.inner,
-            ) {
-                Ok((_, ref attrs)) if contains_skip(attrs) => continue,
-                Ok(m) => m,
-                Err(..) => continue,
-            };
+            let (attrs, items, span) =
+                match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.span) {
+                    Ok((ref attrs, _, _)) if contains_skip(attrs) => continue,
+                    Ok(m) => m,
+                    Err(..) => continue,
+                };
 
             result.push((
                 actual_path,
                 DirectoryOwnership::Owned { relative: None },
-                Module::new(Cow::Owned(m.0), &m.1),
+                Module::new(
+                    span,
+                    Some(Cow::Owned(ast::ModKind::Unloaded)),
+                    Cow::Owned(items),
+                    Cow::Owned(attrs),
+                ),
             ))
         }
         result
diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs
index 5c555e06a80..29248ced2ff 100644
--- a/src/syntux/parser.rs
+++ b/src/syntux/parser.rs
@@ -1,8 +1,8 @@
 use std::panic::{catch_unwind, AssertUnwindSafe};
 use std::path::{Path, PathBuf};
 
-use rustc_ast::ast;
 use rustc_ast::token::{DelimToken, TokenKind};
+use rustc_ast::{ast, ptr};
 use rustc_errors::Diagnostic;
 use rustc_parse::{
     new_parser_from_file,
@@ -109,10 +109,10 @@ impl<'a> Parser<'a> {
         sess: &'a ParseSess,
         path: &Path,
         span: Span,
-    ) -> Result<(ast::Mod, Vec<ast::Attribute>), ParserError> {
+    ) -> Result<(Vec<ast::Attribute>, Vec<ptr::P<ast::Item>>, Span), ParserError> {
         let result = catch_unwind(AssertUnwindSafe(|| {
             let mut parser = new_parser_from_file(sess.inner(), &path, Some(span));
-            match parser.parse_mod(&TokenKind::Eof, ast::Unsafe::No) {
+            match parser.parse_mod(&TokenKind::Eof) {
                 Ok(result) => Some(result),
                 Err(mut e) => {
                     sess.emit_or_cancel_diagnostic(&mut e);
diff --git a/src/visitor.rs b/src/visitor.rs
index 34e8536b7ee..4cd6b8d56d1 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -524,10 +524,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     self.visit_enum(item.ident, &item.vis, def, generics, item.span);
                     self.last_pos = source!(self, item.span).hi();
                 }
-                ast::ItemKind::Mod(ref module) => {
-                    let is_inline = !is_mod_decl(item);
+                ast::ItemKind::Mod(unsafety, ref mod_kind) => {
                     self.format_missing_with_indent(source!(self, item.span).lo());
-                    self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline);
+                    self.format_mod(mod_kind, unsafety, &item.vis, item.span, item.ident, attrs);
                 }
                 ast::ItemKind::MacCall(ref mac) => {
                     self.visit_mac(mac, Some(item.ident), MacroPosition::Item);
@@ -921,8 +920,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         !is_skip_attr(segments)
     }
 
-    fn walk_mod_items(&mut self, m: &ast::Mod) {
-        self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&m.items));
+    fn walk_mod_items(&mut self, items: &Vec<rustc_ast::ptr::P<ast::Item>>) {
+        self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&items));
     }
 
     fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) {
@@ -974,22 +973,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
     fn format_mod(
         &mut self,
-        m: &ast::Mod,
+        mod_kind: &ast::ModKind,
+        unsafety: ast::Unsafe,
         vis: &ast::Visibility,
         s: Span,
         ident: symbol::Ident,
         attrs: &[ast::Attribute],
-        is_internal: bool,
     ) {
         let vis_str = utils::format_visibility(&self.get_context(), vis);
         self.push_str(&*vis_str);
-        self.push_str(format_unsafety(m.unsafety));
+        self.push_str(format_unsafety(unsafety));
         self.push_str("mod ");
         // Calling `to_owned()` to work around borrow checker.
         let ident_str = rewrite_ident(&self.get_context(), ident).to_owned();
         self.push_str(&ident_str);
 
-        if is_internal {
+        if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, inner_span) = mod_kind {
             match self.config.brace_style() {
                 BraceStyle::AlwaysNextLine => {
                     let indent_str = self.block_indent.to_string_with_newline(self.config);
@@ -1001,7 +1000,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             // Hackery to account for the closing }.
             let mod_lo = self.snippet_provider.span_after(source!(self, s), "{");
             let body_snippet =
-                self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi() - BytePos(1)));
+                self.snippet(mk_sp(mod_lo, source!(self, inner_span).hi() - BytePos(1)));
             let body_snippet = body_snippet.trim();
             if body_snippet.is_empty() {
                 self.push_str("}");
@@ -1009,11 +1008,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 self.last_pos = mod_lo;
                 self.block_indent = self.block_indent.block_indent(self.config);
                 self.visit_attrs(attrs, ast::AttrStyle::Inner);
-                self.walk_mod_items(m);
-                let missing_span = self.next_span(m.inner.hi() - BytePos(1));
+                self.walk_mod_items(items);
+                let missing_span = self.next_span(inner_span.hi() - BytePos(1));
                 self.close_block(missing_span, false);
             }
-            self.last_pos = source!(self, m.inner).hi();
+            self.last_pos = source!(self, inner_span).hi();
         } else {
             self.push_str(";");
             self.last_pos = source!(self, s).hi();
@@ -1023,9 +1022,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     pub(crate) fn format_separate_mod(&mut self, m: &Module<'_>, end_pos: BytePos) {
         self.block_indent = Indent::empty();
         if self.visit_attrs(m.attrs(), ast::AttrStyle::Inner) {
-            self.push_skipped_with_span(m.attrs(), m.as_ref().inner, m.as_ref().inner);
+            self.push_skipped_with_span(m.attrs(), m.span, m.span);
         } else {
-            self.walk_mod_items(m.as_ref());
+            self.walk_mod_items(&m.items);
             self.format_missing_with_indent(end_pos);
         }
     }