about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs47
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs24
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs4
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs8
-rw-r--r--compiler/rustc_resolve/src/imports.rs14
-rw-r--r--compiler/rustc_resolve/src/lib.rs5
-rw-r--r--tests/ui/extern/auxiliary/issue-80074-macro-2.rs3
-rw-r--r--tests/ui/extern/auxiliary/issue-80074-macro.rs2
-rw-r--r--tests/ui/extern/issue-80074.rs12
-rw-r--r--tests/ui/extern/issue-80074.stderr31
-rw-r--r--tests/ui/imports/auxiliary/issue-119369-extern.rs2
-rw-r--r--tests/ui/imports/issue-119369.rs14
12 files changed, 149 insertions, 17 deletions
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index e917e7cb02b..01c9e118a11 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4604,3 +4604,50 @@ declare_lint! {
         reference: "issue #X <https://github.com/rust-lang/rust/issues/X>",
     };
 }
+
+declare_lint! {
+    /// The `private_macro_use` lint detects private macros that are imported
+    /// with `#[macro_use]`.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (needs extern crate)
+    /// // extern_macro.rs
+    /// macro_rules! foo_ { () => {}; }
+    /// use foo_ as foo;
+    ///
+    /// // code.rs
+    ///
+    /// #![deny(private_macro_use)]
+    ///
+    /// #[macro_use]
+    /// extern crate extern_macro;
+    ///
+    /// fn main() {
+    ///     foo!();
+    /// }
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// error: cannot find macro `foo` in this scope
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// This lint arises from overlooking visibility checks for macros
+    /// in an external crate.
+    ///
+    /// This is a [future-incompatible] lint to transition this to a
+    /// hard error in the future.
+    ///
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    pub PRIVATE_MACRO_USE,
+    Warn,
+    "detects certain macro bindings that should not be re-exported",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reference: "issue #120192 <https://github.com/rust-lang/rust/issues/120192>",
+    };
+}
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index a4e2f9e3ff8..b855ec8f920 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -1029,9 +1029,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             }
         }
 
-        let macro_use_import = |this: &Self, span| {
+        let macro_use_import = |this: &Self, span, warn_private| {
             this.r.arenas.alloc_import(ImportData {
-                kind: ImportKind::MacroUse,
+                kind: ImportKind::MacroUse { warn_private },
                 root_id: item.id,
                 parent_scope: this.parent_scope,
                 imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
@@ -1048,11 +1048,25 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
         let allow_shadowing = self.parent_scope.expansion == LocalExpnId::ROOT;
         if let Some(span) = import_all {
-            let import = macro_use_import(self, span);
+            let import = macro_use_import(self, span, false);
             self.r.potentially_unused_imports.push(import);
             module.for_each_child(self, |this, ident, ns, binding| {
                 if ns == MacroNS {
-                    let imported_binding = this.r.import(binding, import);
+                    let imported_binding =
+                        if this.r.is_accessible_from(binding.vis, this.parent_scope.module) {
+                            this.r.import(binding, import)
+                        } else if !this.r.is_builtin_macro(binding.res())
+                            && !this.r.macro_use_prelude.contains_key(&ident.name)
+                        {
+                            // - `!r.is_builtin_macro(res)` excluding the built-in macros such as `Debug` or `Hash`.
+                            // - `!r.macro_use_prelude.contains_key(name)` excluding macros defined in other extern
+                            //    crates such as `std`.
+                            // FIXME: This branch should eventually be removed.
+                            let import = macro_use_import(this, span, true);
+                            this.r.import(binding, import)
+                        } else {
+                            return;
+                        };
                     this.add_macro_use_binding(ident.name, imported_binding, span, allow_shadowing);
                 }
             });
@@ -1065,7 +1079,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                     &self.parent_scope,
                 );
                 if let Ok(binding) = result {
-                    let import = macro_use_import(self, ident.span);
+                    let import = macro_use_import(self, ident.span, false);
                     self.r.potentially_unused_imports.push(import);
                     let imported_binding = self.r.import(binding, import);
                     self.add_macro_use_binding(
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 0e43a35ce73..fc72d76c3a7 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -290,7 +290,7 @@ impl Resolver<'_, '_> {
                     || import.expect_vis().is_public()
                     || import.span.is_dummy() =>
                 {
-                    if let ImportKind::MacroUse = import.kind {
+                    if let ImportKind::MacroUse { .. } = import.kind {
                         if !import.span.is_dummy() {
                             self.lint_buffer.buffer_lint(
                                 MACRO_USE_EXTERN_CRATE,
@@ -315,7 +315,7 @@ impl Resolver<'_, '_> {
                         maybe_unused_extern_crates.insert(id, import.span);
                     }
                 }
-                ImportKind::MacroUse => {
+                ImportKind::MacroUse { .. } => {
                     let msg = "unused `#[macro_use]` import";
                     self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.root_id, import.span, msg);
                 }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 4a0c522b6ec..66dfee6c062 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -285,7 +285,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         use NameBindingKind::Import;
         let can_suggest = |binding: NameBinding<'_>, import: self::Import<'_>| {
             !binding.span.is_dummy()
-                && !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport)
+                && !matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport)
         };
         let import = match (&new_binding.kind, &old_binding.kind) {
             // If there are two imports where one or both have attributes then prefer removing the
@@ -1819,9 +1819,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         next_ident = source;
                         Some(binding)
                     }
-                    ImportKind::Glob { .. } | ImportKind::MacroUse | ImportKind::MacroExport => {
-                        Some(binding)
-                    }
+                    ImportKind::Glob { .. }
+                    | ImportKind::MacroUse { .. }
+                    | ImportKind::MacroExport => Some(binding),
                     ImportKind::ExternCrate { .. } => None,
                 },
                 _ => None,
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index f846dbec2c6..ad60caed354 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -80,7 +80,11 @@ pub(crate) enum ImportKind<'a> {
         target: Ident,
         id: NodeId,
     },
-    MacroUse,
+    MacroUse {
+        /// A field has been added indicating whether it should be reported as a lint,
+        /// addressing issue#119301.
+        warn_private: bool,
+    },
     MacroExport,
 }
 
@@ -127,7 +131,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
                 .field("target", target)
                 .field("id", id)
                 .finish(),
-            MacroUse => f.debug_struct("MacroUse").finish(),
+            MacroUse { .. } => f.debug_struct("MacroUse").finish(),
             MacroExport => f.debug_struct("MacroExport").finish(),
         }
     }
@@ -197,7 +201,7 @@ impl<'a> ImportData<'a> {
             ImportKind::Single { id, .. }
             | ImportKind::Glob { id, .. }
             | ImportKind::ExternCrate { id, .. } => Some(id),
-            ImportKind::MacroUse | ImportKind::MacroExport => None,
+            ImportKind::MacroUse { .. } | ImportKind::MacroExport => None,
         }
     }
 
@@ -207,7 +211,7 @@ impl<'a> ImportData<'a> {
             ImportKind::Single { id, .. } => Reexport::Single(to_def_id(id)),
             ImportKind::Glob { id, .. } => Reexport::Glob(to_def_id(id)),
             ImportKind::ExternCrate { id, .. } => Reexport::ExternCrate(to_def_id(id)),
-            ImportKind::MacroUse => Reexport::MacroUse,
+            ImportKind::MacroUse { .. } => Reexport::MacroUse,
             ImportKind::MacroExport => Reexport::MacroExport,
         }
     }
@@ -1482,7 +1486,7 @@ fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String {
         ImportKind::Single { source, .. } => source.to_string(),
         ImportKind::Glob { .. } => "*".to_string(),
         ImportKind::ExternCrate { .. } => "<extern crate>".to_string(),
-        ImportKind::MacroUse => "#[macro_use]".to_string(),
+        ImportKind::MacroUse { .. } => "#[macro_use]".to_string(),
         ImportKind::MacroExport => "#[macro_export]".to_string(),
     }
 }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 341c566d97f..7b4f3383c3f 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -55,6 +55,7 @@ use rustc_middle::span_bug;
 use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt};
 use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
 use rustc_query_system::ich::StableHashingContext;
+use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
 use rustc_session::lint::LintBuffer;
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -1799,6 +1800,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
         }
         if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind {
+            if let ImportKind::MacroUse { warn_private: true } = import.kind {
+                let msg = format!("macro `{ident}` is private");
+                self.lint_buffer().buffer_lint(PRIVATE_MACRO_USE, import.root_id, ident.span, msg);
+            }
             // Avoid marking `extern crate` items that refer to a name from extern prelude,
             // but not introduce it, as used if they are accessed from lexical scope.
             if is_lexical_scope {
diff --git a/tests/ui/extern/auxiliary/issue-80074-macro-2.rs b/tests/ui/extern/auxiliary/issue-80074-macro-2.rs
new file mode 100644
index 00000000000..bc87a2b5434
--- /dev/null
+++ b/tests/ui/extern/auxiliary/issue-80074-macro-2.rs
@@ -0,0 +1,3 @@
+// edition:2018
+
+macro_rules! m { () => {}; }
diff --git a/tests/ui/extern/auxiliary/issue-80074-macro.rs b/tests/ui/extern/auxiliary/issue-80074-macro.rs
index 30e0f19ab8d..3e912d97715 100644
--- a/tests/ui/extern/auxiliary/issue-80074-macro.rs
+++ b/tests/ui/extern/auxiliary/issue-80074-macro.rs
@@ -2,3 +2,5 @@
 
 macro_rules! foo_ { () => {}; }
 use foo_ as foo;
+
+macro_rules! bar { () => {}; }
diff --git a/tests/ui/extern/issue-80074.rs b/tests/ui/extern/issue-80074.rs
index f83027d4abf..6e4f176de82 100644
--- a/tests/ui/extern/issue-80074.rs
+++ b/tests/ui/extern/issue-80074.rs
@@ -1,10 +1,20 @@
 // edition:2018
-// build-pass
 // aux-crate:issue_80074=issue-80074-macro.rs
+// aux-crate:issue_80074_2=issue-80074-macro-2.rs
 
 #[macro_use]
 extern crate issue_80074;
 
+#[macro_use(m)]
+extern crate issue_80074_2;
+//~^^ ERROR: imported macro not found
+
 fn main() {
     foo!();
+    //~^ WARN: macro `foo` is private
+    //~| WARN: it will become a hard error in a future release!
+    bar!();
+    //~^ ERROR: cannot find macro `bar` in this scope
+    m!();
+    //~^ ERROR: cannot find macro `m` in this scope
 }
diff --git a/tests/ui/extern/issue-80074.stderr b/tests/ui/extern/issue-80074.stderr
new file mode 100644
index 00000000000..b30b761593e
--- /dev/null
+++ b/tests/ui/extern/issue-80074.stderr
@@ -0,0 +1,31 @@
+error[E0469]: imported macro not found
+  --> $DIR/issue-80074.rs:8:13
+   |
+LL | #[macro_use(m)]
+   |             ^
+
+error: cannot find macro `bar` in this scope
+  --> $DIR/issue-80074.rs:16:5
+   |
+LL |     bar!();
+   |     ^^^
+
+error: cannot find macro `m` in this scope
+  --> $DIR/issue-80074.rs:18:5
+   |
+LL |     m!();
+   |     ^
+
+warning: macro `foo` is private
+  --> $DIR/issue-80074.rs:13:5
+   |
+LL |     foo!();
+   |     ^^^
+   |
+   = 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 #120192 <https://github.com/rust-lang/rust/issues/120192>
+   = note: `#[warn(private_macro_use)]` on by default
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0469`.
diff --git a/tests/ui/imports/auxiliary/issue-119369-extern.rs b/tests/ui/imports/auxiliary/issue-119369-extern.rs
new file mode 100644
index 00000000000..278cbfa1e3e
--- /dev/null
+++ b/tests/ui/imports/auxiliary/issue-119369-extern.rs
@@ -0,0 +1,2 @@
+use std::vec;
+use std::hash::Hash;
diff --git a/tests/ui/imports/issue-119369.rs b/tests/ui/imports/issue-119369.rs
new file mode 100644
index 00000000000..0b4dc3f4654
--- /dev/null
+++ b/tests/ui/imports/issue-119369.rs
@@ -0,0 +1,14 @@
+// check-pass
+// aux-build: issue-119369-extern.rs
+
+// https://github.com/rust-lang/rust/pull/119369#issuecomment-1874905662
+
+#[macro_use]
+extern crate issue_119369_extern;
+
+#[derive(Hash)]
+struct A;
+
+fn main() {
+    let _: Vec<i32> = vec![];
+}