about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Mládek <david.mladek.cz@gmail.com>2025-07-12 16:44:34 +0200
committerDavid Mládek <david.mladek.cz@gmail.com>2025-07-15 15:44:25 +0200
commit8b868fa534a8b660a5b8051a5c883d4c15c5b70e (patch)
tree4d08723737ccb188c243207aef8ccdde1e28e493
parent4a77a62e5611890dd275e17de0fb1694e4ff9a28 (diff)
downloadrust-8b868fa534a8b660a5b8051a5c883d4c15c5b70e.tar.gz
rust-8b868fa534a8b660a5b8051a5c883d4c15c5b70e.zip
Implement resolver warnings about reexporting private dependencies
-rw-r--r--compiler/rustc_lint/messages.ftl3
-rw-r--r--compiler/rustc_lint/src/early/diagnostics.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs8
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs5
-rw-r--r--compiler/rustc_resolve/src/imports.rs25
-rw-r--r--tests/ui/privacy/pub-priv-dep/pub-priv1.rs14
-rw-r--r--tests/ui/privacy/pub-priv-dep/pub-priv1.stderr46
7 files changed, 90 insertions, 14 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 8d9f2385b71..183db43ca76 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -744,6 +744,9 @@ lint_redundant_semicolons_suggestion = remove {$multiple_semicolons ->
         *[false] this semicolon
     }
 
+lint_reexport_private_dependency =
+    {$kind} `{$name}` from private dependency '{$krate}' is re-exported
+
 lint_remove_mut_from_pattern = remove `mut` from the parameter
 
 lint_removed_lint = lint `{$name}` has been removed: {$reason}
diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs
index 653559009cc..f0fbf5bc81e 100644
--- a/compiler/rustc_lint/src/early/diagnostics.rs
+++ b/compiler/rustc_lint/src/early/diagnostics.rs
@@ -351,6 +351,9 @@ pub fn decorate_builtin_lint(
             }
             .decorate_lint(diag);
         }
+        BuiltinLintDiag::ReexportPrivateDependency { name, kind, krate } => {
+            lints::ReexportPrivateDependency { name, kind, krate }.decorate_lint(diag);
+        }
         BuiltinLintDiag::UnusedQualifications { removal_span } => {
             lints::UnusedQualifications { removal_span }.decorate_lint(diag);
         }
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 21148833eaf..fc3c1073259 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -3081,6 +3081,14 @@ pub(crate) struct HiddenGlobReexports {
 }
 
 #[derive(LintDiagnostic)]
+#[diag(lint_reexport_private_dependency)]
+pub(crate) struct ReexportPrivateDependency {
+    pub name: String,
+    pub kind: String,
+    pub krate: Symbol,
+}
+
+#[derive(LintDiagnostic)]
 #[diag(lint_unnecessary_qualification)]
 pub(crate) struct UnusedQualifications {
     #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index cd402c9234f..fe068d96b74 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -739,6 +739,11 @@ pub enum BuiltinLintDiag {
         /// The local binding that shadows the glob reexport.
         private_item_span: Span,
     },
+    ReexportPrivateDependency {
+        name: String,
+        kind: String,
+        krate: Symbol,
+    },
     UnusedQualifications {
         /// The span of the unnecessarily-qualified path to remove.
         removal_span: Span,
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index b2f6ee6563c..9e8eac75fa1 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -14,8 +14,8 @@ use rustc_middle::metadata::{ModChild, Reexport};
 use rustc_middle::{span_bug, ty};
 use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::{
-    AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE,
-    REDUNDANT_IMPORTS, UNUSED_IMPORTS,
+    AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS,
+    PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS,
 };
 use rustc_session::parse::feature_err;
 use rustc_span::edit_distance::find_best_match_for_name;
@@ -696,6 +696,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         }
                     }
                 }
+
+                if let NameBindingKind::Import { import, .. } = binding.kind
+                    && let Some(binding_id) = import.id()
+                    && let import_def_id = self.local_def_id(binding_id)
+                    && self.effective_visibilities.is_exported(import_def_id)
+                    && let Res::Def(reexported_kind, reexported_def_id) = binding.res()
+                    && !matches!(reexported_kind, DefKind::Ctor(..))
+                    && !reexported_def_id.is_local()
+                    && self.tcx.is_private_dep(reexported_def_id.krate)
+                {
+                    self.lint_buffer.buffer_lint(
+                        EXPORTED_PRIVATE_DEPENDENCIES,
+                        binding_id,
+                        binding.span,
+                        BuiltinLintDiag::ReexportPrivateDependency {
+                            kind: binding.res().descr().to_string(),
+                            name: key.ident.name.to_string(),
+                            krate: self.tcx.crate_name(reexported_def_id.krate),
+                        },
+                    );
+                }
             }
         }
     }
diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
index 877029f3de3..192ca0db8bd 100644
--- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
+++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
@@ -9,10 +9,10 @@
 #![deny(exported_private_dependencies)]
 
 // This crate is a private dependency
-// FIXME: This should trigger.
 pub extern crate priv_dep;
+//~^ ERROR crate `priv_dep` from private dependency 'priv_dep' is re-exported
 // This crate is a public dependency
-extern crate pub_dep;
+pub extern crate pub_dep;
 // This crate is a private dependency
 extern crate pm;
 
@@ -91,16 +91,16 @@ pub struct AllowedPrivType {
     pub allowed: OtherType,
 }
 
-// FIXME: This should trigger.
 pub use priv_dep::m;
-// FIXME: This should trigger.
+//~^ ERROR macro `m` from private dependency 'priv_dep' is re-exported
 pub use pm::fn_like;
-// FIXME: This should trigger.
+//~^ ERROR macro `fn_like` from private dependency 'pm' is re-exported
 pub use pm::PmDerive;
-// FIXME: This should trigger.
+//~^ ERROR macro `PmDerive` from private dependency 'pm' is re-exported
 pub use pm::pm_attr;
+//~^ ERROR macro `pm_attr` from private dependency 'pm' is re-exported
 
-// FIXME: This should trigger.
 pub use priv_dep::E::V1;
+//~^ ERROR variant `V1` from private dependency 'priv_dep' is re-exported
 
 fn main() {}
diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
index adfe13424cd..9da47827be4 100644
--- a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
+++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
@@ -1,8 +1,8 @@
-error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:29:5
+error: crate `priv_dep` from private dependency 'priv_dep' is re-exported
+  --> $DIR/pub-priv1.rs:12:1
    |
-LL |     pub field: OtherType,
-   |     ^^^^^^^^^^^^^^^^^^^^
+LL | pub extern crate priv_dep;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/pub-priv1.rs:9:9
@@ -10,6 +10,42 @@ note: the lint level is defined here
 LL | #![deny(exported_private_dependencies)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: macro `m` from private dependency 'priv_dep' is re-exported
+  --> $DIR/pub-priv1.rs:94:9
+   |
+LL | pub use priv_dep::m;
+   |         ^^^^^^^^^^^
+
+error: macro `fn_like` from private dependency 'pm' is re-exported
+  --> $DIR/pub-priv1.rs:96:9
+   |
+LL | pub use pm::fn_like;
+   |         ^^^^^^^^^^^
+
+error: derive macro `PmDerive` from private dependency 'pm' is re-exported
+  --> $DIR/pub-priv1.rs:98:9
+   |
+LL | pub use pm::PmDerive;
+   |         ^^^^^^^^^^^^
+
+error: attribute macro `pm_attr` from private dependency 'pm' is re-exported
+  --> $DIR/pub-priv1.rs:100:9
+   |
+LL | pub use pm::pm_attr;
+   |         ^^^^^^^^^^^
+
+error: variant `V1` from private dependency 'priv_dep' is re-exported
+  --> $DIR/pub-priv1.rs:103:9
+   |
+LL | pub use priv_dep::E::V1;
+   |         ^^^^^^^^^^^^^^^
+
+error: type `OtherType` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:29:5
+   |
+LL |     pub field: OtherType,
+   |     ^^^^^^^^^^^^^^^^^^^^
+
 error: type `OtherType` from private dependency 'priv_dep' in public interface
   --> $DIR/pub-priv1.rs:36:5
    |
@@ -90,5 +126,5 @@ LL | impl PubTraitOnPrivate for OtherType {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 14 previous errors
+error: aborting due to 20 previous errors