about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock6
-rw-r--r--compiler/rustc_ast/src/ast.rs2
-rw-r--r--compiler/rustc_expand/src/expand.rs20
-rw-r--r--compiler/rustc_expand/src/module.rs58
-rw-r--r--compiler/rustc_resolve/src/macros.rs27
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--src/test/ui/conditional-compilation/inner-cfg-non-inline-mod.rs7
-rw-r--r--src/test/ui/conditional-compilation/module_with_cfg.rs3
-rw-r--r--src/test/ui/proc-macro/inner-attr-non-inline-mod.rs18
-rw-r--r--src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr40
-rw-r--r--src/test/ui/proc-macro/inner-attr-non-inline-mod.stdout76
-rw-r--r--src/test/ui/proc-macro/module_with_attrs.rs4
12 files changed, 230 insertions, 32 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5ca91f42bdc..3c278a6a491 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4774,7 +4774,7 @@ version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
 dependencies = [
- "semver-parser 0.10.1",
+ "semver-parser 0.10.2",
  "serde",
 ]
 
@@ -4786,9 +4786,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 
 [[package]]
 name = "semver-parser"
-version = "0.10.1"
+version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ef146c2ad5e5f4b037cd6ce2ebb775401729b19a82040c1beac9d36c7d1428"
+checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
 dependencies = [
  "pest",
 ]
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index d6297addc0c..a934bdd7980 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2297,7 +2297,7 @@ impl FnRetTy {
     }
 }
 
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
 pub enum Inline {
     Yes,
     No,
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index dd2eaa0f3d5..a1e5979f62d 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1282,16 +1282,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 let (file_path, dir_path, dir_ownership) = match mod_kind {
                     ModKind::Loaded(_, inline, _) => {
                         // Inline `mod foo { ... }`, but we still need to push directories.
-                        assert!(
-                            *inline == Inline::Yes,
-                            "`mod` item is loaded from a file for the second time"
-                        );
                         let (dir_path, dir_ownership) = mod_dir_path(
                             &self.cx.sess,
                             ident,
                             &attrs,
                             &self.cx.current_expansion.module,
                             self.cx.current_expansion.dir_ownership,
+                            *inline,
                         );
                         item.attrs = attrs;
                         (None, dir_path, dir_ownership)
@@ -1322,10 +1319,19 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                         item.attrs = attrs;
                         if item.attrs.len() > old_attrs_len {
                             // If we loaded an out-of-line module and added some inner attributes,
-                            // then we need to re-configure it.
-                            // FIXME: Attributes also need to be recollected
-                            // for resolution and expansion.
+                            // then we need to re-configure it and re-collect attributes for
+                            // resolution and expansion.
                             item = configure!(self, item);
+
+                            if let Some(attr) = self.take_first_attr(&mut item) {
+                                return self
+                                    .collect_attr(
+                                        attr,
+                                        Annotatable::Item(item),
+                                        AstFragmentKind::Items,
+                                    )
+                                    .make_items();
+                            }
                         }
                         (Some(file_path), dir_path, dir_ownership)
                     }
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 2ec656d4895..c5ce0baaa8f 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -1,6 +1,6 @@
 use crate::base::ModuleData;
 use rustc_ast::ptr::P;
-use rustc_ast::{token, Attribute, Item};
+use rustc_ast::{token, Attribute, Inline, Item};
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_parse::new_parser_from_file;
 use rustc_session::parse::ParseSess;
@@ -83,29 +83,49 @@ crate fn mod_dir_path(
     attrs: &[Attribute],
     module: &ModuleData,
     mut dir_ownership: DirOwnership,
+    inline: Inline,
 ) -> (PathBuf, DirOwnership) {
-    if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) {
-        // For inline modules file path from `#[path]` is actually the directory path
-        // for historical reasons, so we don't pop the last segment here.
-        return (file_path, DirOwnership::Owned { relative: None });
-    }
+    match inline {
+        Inline::Yes => {
+            if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) {
+                // For inline modules file path from `#[path]` is actually the directory path
+                // for historical reasons, so we don't pop the last segment here.
+                return (file_path, DirOwnership::Owned { relative: None });
+            }
 
-    // We have to push on the current module name in the case of relative
-    // paths in order to ensure that any additional module paths from inline
-    // `mod x { ... }` come after the relative extension.
-    //
-    // For example, a `mod z { ... }` inside `x/y.rs` should set the current
-    // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
-    let mut dir_path = module.dir_path.clone();
-    if let DirOwnership::Owned { relative } = &mut dir_ownership {
-        if let Some(ident) = relative.take() {
-            // Remove the relative offset.
+            // We have to push on the current module name in the case of relative
+            // paths in order to ensure that any additional module paths from inline
+            // `mod x { ... }` come after the relative extension.
+            //
+            // For example, a `mod z { ... }` inside `x/y.rs` should set the current
+            // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
+            let mut dir_path = module.dir_path.clone();
+            if let DirOwnership::Owned { relative } = &mut dir_ownership {
+                if let Some(ident) = relative.take() {
+                    // Remove the relative offset.
+                    dir_path.push(&*ident.as_str());
+                }
+            }
             dir_path.push(&*ident.as_str());
+
+            (dir_path, dir_ownership)
         }
-    }
-    dir_path.push(&*ident.as_str());
+        Inline::No => {
+            // FIXME: This is a subset of `parse_external_mod` without actual parsing,
+            // check whether the logic for unloaded, loaded and inline modules can be unified.
+            let file_path = mod_file_path(sess, ident, &attrs, &module.dir_path, dir_ownership)
+                .map(|mp| {
+                    dir_ownership = mp.dir_ownership;
+                    mp.file_path
+                })
+                .unwrap_or_default();
+
+            // Extract the directory path for submodules of the module.
+            let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
 
-    (dir_path, dir_ownership)
+            (dir_path, dir_ownership)
+        }
+    }
 }
 
 fn mod_file_path<'a>(
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 2d149c476a6..2e47d4cecee 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -6,7 +6,7 @@ use crate::Namespace::*;
 use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BuiltinMacroState, Determinacy};
 use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
 use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
-use rustc_ast::{self as ast, NodeId};
+use rustc_ast::{self as ast, Inline, ItemKind, ModKind, NodeId};
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_ast_pretty::pprust;
 use rustc_attr::StabilityLevel;
@@ -14,6 +14,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::struct_span_err;
+use rustc_expand::base::Annotatable;
 use rustc_expand::base::{Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::compile_declarative_macro;
 use rustc_expand::expand::{AstFragment, Invocation, InvocationKind};
@@ -153,6 +154,26 @@ crate fn registered_attrs_and_tools(
     (registered_attrs, registered_tools)
 }
 
+// Some feature gates for inner attributes are reported as lints for backward compatibility.
+fn soft_custom_inner_attributes_gate(path: &ast::Path, invoc: &Invocation) -> bool {
+    match &path.segments[..] {
+        // `#![test]`
+        [seg] if seg.ident.name == sym::test => return true,
+        // `#![rustfmt::skip]` on out-of-line modules
+        [seg1, seg2] if seg1.ident.name == sym::rustfmt && seg2.ident.name == sym::skip => {
+            if let InvocationKind::Attr { item, .. } = &invoc.kind {
+                if let Annotatable::Item(item) = item {
+                    if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _)) = item.kind {
+                        return true;
+                    }
+                }
+            }
+        }
+        _ => {}
+    }
+    false
+}
+
 impl<'a> ResolverExpand for Resolver<'a> {
     fn next_node_id(&mut self) -> NodeId {
         self.next_node_id()
@@ -267,6 +288,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
             parent_scope,
             node_id,
             force,
+            soft_custom_inner_attributes_gate(path, invoc),
         )?;
 
         let span = invoc.span();
@@ -440,6 +462,7 @@ impl<'a> Resolver<'a> {
         parent_scope: &ParentScope<'a>,
         node_id: NodeId,
         force: bool,
+        soft_custom_inner_attributes_gate: bool,
     ) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
         let (ext, res) = match self.resolve_macro_path(path, Some(kind), parent_scope, true, force)
         {
@@ -507,7 +530,7 @@ impl<'a> Resolver<'a> {
                 Res::NonMacroAttr(..) => "custom inner attributes are unstable",
                 _ => unreachable!(),
             };
-            if path == &sym::test {
+            if soft_custom_inner_attributes_gate {
                 self.session.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg);
             } else {
                 feature_err(&self.session.parse_sess, sym::custom_inner_attributes, path.span, msg)
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 79ca3c194cc..4fcb8b6c1b7 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1111,6 +1111,7 @@ symbols! {
         size_of,
         size_of_val,
         sized,
+        skip,
         slice,
         slice_alloc,
         slice_patterns,
diff --git a/src/test/ui/conditional-compilation/inner-cfg-non-inline-mod.rs b/src/test/ui/conditional-compilation/inner-cfg-non-inline-mod.rs
new file mode 100644
index 00000000000..af5a6462e8a
--- /dev/null
+++ b/src/test/ui/conditional-compilation/inner-cfg-non-inline-mod.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+mod module_with_cfg;
+
+mod module_with_cfg {} // Ok, the module above is configured away by an inner attribute.
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/module_with_cfg.rs b/src/test/ui/conditional-compilation/module_with_cfg.rs
new file mode 100644
index 00000000000..56c4baadf22
--- /dev/null
+++ b/src/test/ui/conditional-compilation/module_with_cfg.rs
@@ -0,0 +1,3 @@
+// ignore-test
+
+#![cfg_attr(all(), cfg(FALSE))]
diff --git a/src/test/ui/proc-macro/inner-attr-non-inline-mod.rs b/src/test/ui/proc-macro/inner-attr-non-inline-mod.rs
new file mode 100644
index 00000000000..30c2666df47
--- /dev/null
+++ b/src/test/ui/proc-macro/inner-attr-non-inline-mod.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Z span-debug
+// error-pattern:custom inner attributes are unstable
+// error-pattern:inner macro attributes are unstable
+// error-pattern:this was previously accepted
+// aux-build:test-macros.rs
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+#[deny(unused_attributes)]
+mod module_with_attrs;
+//~^ ERROR non-inline modules in proc macro input are unstable
+//~| ERROR custom inner attributes are unstable
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr
new file mode 100644
index 00000000000..4286896dfc3
--- /dev/null
+++ b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr
@@ -0,0 +1,40 @@
+error[E0658]: inner macro attributes are unstable
+  --> $DIR/module_with_attrs.rs:4:4
+   |
+LL | #![print_attr]
+   |    ^^^^^^^^^^
+   |
+   = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
+   = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
+
+error[E0658]: non-inline modules in proc macro input are unstable
+  --> $DIR/inner-attr-non-inline-mod.rs:14:1
+   |
+LL | mod module_with_attrs;
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+   = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0658]: custom inner attributes are unstable
+  --> $DIR/inner-attr-non-inline-mod.rs:14:1
+   |
+LL | mod module_with_attrs;
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
+   = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
+
+error: custom inner attributes are unstable
+  --> $DIR/module_with_attrs.rs:3:4
+   |
+LL | #![rustfmt::skip]
+   |    ^^^^^^^^^^^^^
+   |
+   = note: `#[deny(soft_unstable)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/inner-attr-non-inline-mod.stdout b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stdout
new file mode 100644
index 00000000000..dbef342ef24
--- /dev/null
+++ b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stdout
@@ -0,0 +1,76 @@
+PRINT-ATTR INPUT (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { # ! [rustfmt :: skip] }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Punct {
+        ch: '#',
+        spacing: Alone,
+        span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+    },
+    Group {
+        delimiter: Bracket,
+        stream: TokenStream [
+            Ident {
+                ident: "deny",
+                span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+            },
+            Group {
+                delimiter: Parenthesis,
+                stream: TokenStream [
+                    Ident {
+                        ident: "unused_attributes",
+                        span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+                    },
+                ],
+                span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+            },
+        ],
+        span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+    },
+    Ident {
+        ident: "mod",
+        span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+    },
+    Ident {
+        ident: "module_with_attrs",
+        span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Punct {
+                ch: '#',
+                spacing: Joint,
+                span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+            },
+            Punct {
+                ch: '!',
+                spacing: Alone,
+                span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+            },
+            Group {
+                delimiter: Bracket,
+                stream: TokenStream [
+                    Ident {
+                        ident: "rustfmt",
+                        span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+                    },
+                    Punct {
+                        ch: ':',
+                        spacing: Joint,
+                        span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+                    },
+                    Punct {
+                        ch: ':',
+                        spacing: Alone,
+                        span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+                    },
+                    Ident {
+                        ident: "skip",
+                        span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+                    },
+                ],
+                span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+            },
+        ],
+        span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+    },
+]
diff --git a/src/test/ui/proc-macro/module_with_attrs.rs b/src/test/ui/proc-macro/module_with_attrs.rs
new file mode 100644
index 00000000000..63e66a62ac3
--- /dev/null
+++ b/src/test/ui/proc-macro/module_with_attrs.rs
@@ -0,0 +1,4 @@
+// ignore-test
+
+#![rustfmt::skip]
+#![print_attr]