diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl index 7785f1a7f81fb..e6b96d7f1bfd3 100644 --- a/compiler/rustc_privacy/messages.ftl +++ b/compiler/rustc_privacy/messages.ftl @@ -8,6 +8,7 @@ privacy_from_private_dep_in_public_interface = privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interface .label = can't leak {$vis_descr} {$kind} .visibility_label = `{$descr}` declared as {$vis_descr} + .suggestion = consider adding `{$vis_sugg}` in front of it privacy_item_is_private = {$kind} `{$descr}` is private .label = private {$kind} diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs index ee04c335f2bd1..613dab8c73660 100644 --- a/compiler/rustc_privacy/src/errors.rs +++ b/compiler/rustc_privacy/src/errors.rs @@ -48,6 +48,7 @@ pub struct UnnamedItemIsPrivate { } #[derive(Diagnostic)] +#[help] #[diag(privacy_in_public_interface, code = E0446)] pub struct InPublicInterface<'a> { #[primary_span] @@ -58,6 +59,9 @@ pub struct InPublicInterface<'a> { pub descr: DiagArgFromDisplay<'a>, #[label(privacy_visibility_label)] pub vis_span: Span, + #[suggestion(code = "{vis_sugg}", applicability = "maybe-incorrect", style = "verbose")] + pub data: Span, + pub vis_sugg: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index a78f7e65981ab..f9ba99dd8127a 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1337,12 +1337,31 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } }; + // FIXME: this code was adapted from the above `vis_descr` computation, + // but it's not clear if it's correct. + let vis_sugg = match self.required_visibility { + ty::Visibility::Public => "pub", + ty::Visibility::Restricted(vis_def_id) => { + if vis_def_id + == self.tcx.parent_module_from_def_id(local_def_id).to_local_def_id() + { + "???FIXME???" + } else if vis_def_id.is_top_level_module() { + "pub(crate)" + } else { + "???FIXME???" + } + } + }; + self.tcx.dcx().emit_err(InPublicInterface { span, vis_descr, kind, descr: descr.into(), vis_span, + data: vis_span, + vis_sugg, }); return false; } diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr index 043fa34d605ab..51749adc90975 100644 --- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr @@ -6,6 +6,11 @@ LL | type AssocTy = Const<{ my_const_fn(U) }>; ... LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private + | +help: consider adding `pub` in front of it + | +LL | pub { + | ~~~ error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0446.stderr b/tests/ui/error-codes/E0446.stderr index 2951e69d1c263..4ca98ac63b403 100644 --- a/tests/ui/error-codes/E0446.stderr +++ b/tests/ui/error-codes/E0446.stderr @@ -6,6 +6,11 @@ LL | struct Bar; ... LL | type Alias1 = Bar; | ^^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error[E0446]: private trait `PrivTr` in public interface --> $DIR/E0446.rs:11:5 @@ -15,6 +20,11 @@ LL | trait PrivTr {} ... LL | type Alias2 = Box; | ^^^^^^^^^^^ can't leak private trait + | +help: consider adding `pub` in front of it + | +LL | pub {} + | ~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/privacy/issue-30079.stderr b/tests/ui/privacy/issue-30079.stderr index f1facba7cd230..db5c546eadbe2 100644 --- a/tests/ui/privacy/issue-30079.stderr +++ b/tests/ui/privacy/issue-30079.stderr @@ -19,6 +19,11 @@ LL | struct Priv; LL | impl ::std::ops::Deref for ::SemiPriv { LL | type Target = Priv; | ^^^^^^^^^^^ can't leak private type + | +help: consider adding `pub(crate)` in front of it + | +LL | pub(crate); + | ~~~~~~~~~~ error[E0446]: private type `m3::Priv` in public interface --> $DIR/issue-30079.rs:34:9 @@ -28,6 +33,11 @@ LL | struct Priv; LL | impl ::SemiPrivTrait for () { LL | type Assoc = Priv; | ^^^^^^^^^^ can't leak private type + | +help: consider adding `pub(crate)` in front of it + | +LL | pub(crate); + | ~~~~~~~~~~ error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/privacy/private-in-public-assoc-ty.stderr b/tests/ui/privacy/private-in-public-assoc-ty.stderr index 0931e6d9971ea..7f9e19a899fc1 100644 --- a/tests/ui/privacy/private-in-public-assoc-ty.stderr +++ b/tests/ui/privacy/private-in-public-assoc-ty.stderr @@ -6,6 +6,11 @@ LL | struct Priv; ... LL | type A = Priv; | ^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ warning: trait `PrivTr` is more private than the item `PubTr::Alias1` --> $DIR/private-in-public-assoc-ty.rs:24:9 @@ -52,6 +57,11 @@ LL | struct Priv; ... LL | type Alias4 = Priv; | ^^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error[E0446]: private type `Priv` in public interface --> $DIR/private-in-public-assoc-ty.rs:38:9 @@ -61,6 +71,11 @@ LL | struct Priv; ... LL | type Alias1 = Priv; | ^^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error[E0446]: private trait `PrivTr` in public interface --> $DIR/private-in-public-assoc-ty.rs:41:9 @@ -70,6 +85,11 @@ LL | trait PrivTr {} ... LL | type Exist = impl PrivTr; | ^^^^^^^^^^ can't leak private trait + | +help: consider adding `pub` in front of it + | +LL | pub {} + | ~~~ error: aborting due to 4 previous errors; 3 warnings emitted diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr index ac7e5547de914..69bbf33b7786b 100644 --- a/tests/ui/privacy/private-in-public-warn.stderr +++ b/tests/ui/privacy/private-in-public-warn.stderr @@ -59,6 +59,11 @@ LL | struct Priv; ... LL | type Alias = Priv; | ^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error: type `types::Priv` is more private than the item `Tr::f1` --> $DIR/private-in-public-warn.rs:23:9 @@ -128,6 +133,11 @@ LL | struct Priv; ... LL | type Alias = Priv; | ^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error: trait `traits::PrivTr` is more private than the item `traits::Alias` --> $DIR/private-in-public-warn.rs:41:5 @@ -310,6 +320,11 @@ LL | struct Priv; ... LL | type Alias = Priv; | ^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error: type `aliases_pub::Priv` is more private than the item `aliases_pub::::f` --> $DIR/private-in-public-warn.rs:180:9 @@ -331,6 +346,11 @@ LL | struct Priv; ... LL | type Check = Priv; | ^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public-warn.rs:186:9 @@ -340,6 +360,11 @@ LL | struct Priv; ... LL | type Check = Priv; | ^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public-warn.rs:189:9 @@ -349,6 +374,11 @@ LL | struct Priv; ... LL | type Check = Priv; | ^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public-warn.rs:192:9 @@ -358,6 +388,11 @@ LL | struct Priv; ... LL | type Check = Priv; | ^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error: trait `PrivTr1` is more private than the item `aliases_priv::Tr1` --> $DIR/private-in-public-warn.rs:222:5 diff --git a/tests/ui/privacy/private-inferred-type.stderr b/tests/ui/privacy/private-inferred-type.stderr index fc3f9ab62bfa9..2552ef32bed87 100644 --- a/tests/ui/privacy/private-inferred-type.stderr +++ b/tests/ui/privacy/private-inferred-type.stderr @@ -6,6 +6,11 @@ LL | struct Priv; ... LL | impl TraitWithAssocTy for u8 { type AssocTy = Priv; } | ^^^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error[E0446]: private type `S2` in public interface --> $DIR/private-inferred-type.rs:83:9 @@ -15,6 +20,11 @@ LL | struct S2; ... LL | type Target = S2Alias; | ^^^^^^^^^^^ can't leak private type + | +help: consider adding `pub` in front of it + | +LL | pub; + | ~~~ error: type `Priv` is private --> $DIR/private-inferred-type.rs:97:9 diff --git a/tests/ui/privacy/where-priv-type.stderr b/tests/ui/privacy/where-priv-type.stderr index 126330b14a63f..7a53b609e81bd 100644 --- a/tests/ui/privacy/where-priv-type.stderr +++ b/tests/ui/privacy/where-priv-type.stderr @@ -76,6 +76,11 @@ LL | type AssocTy = Const<{ my_const_fn(U) }>; ... LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private + | +help: consider adding `pub` in front of it + | +LL | pub { + | ~~~ error: aborting due to 1 previous error; 5 warnings emitted