Skip to content

Commit ec49af7

Browse files
committed
Prefer pub(super) in unreachable_pub lint suggestion
1 parent a0d98ff commit ec49af7

File tree

7 files changed

+211
-30
lines changed

7 files changed

+211
-30
lines changed

compiler/rustc_lint/src/builtin.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,12 +1298,38 @@ impl UnreachablePub {
12981298
let mut applicability = Applicability::MachineApplicable;
12991299
if cx.tcx.visibility(def_id).is_public() && !cx.effective_visibilities.is_reachable(def_id)
13001300
{
1301+
// prefer suggesting `pub(super)` instead of `pub(crate)` when possible
1302+
let new_vis = match cx.tcx.opt_parent(def_id.into()) {
1303+
Some(parent_def_id) => match cx.tcx.visibility(parent_def_id) {
1304+
// parent is either `pub(crate)`, `pub(self)` or `pub(in ...)`
1305+
ty::Visibility::Restricted(restricted_id) => {
1306+
if let Some(local_parent_def_id) = parent_def_id.as_local()
1307+
&& restricted_id
1308+
== cx.tcx.parent_module_from_def_id(local_parent_def_id).into()
1309+
{
1310+
// parent is `pub(self)`, current item can only be used by parent
1311+
"pub(super)"
1312+
} else {
1313+
// parent is `pub(crate)` or `pub(in ...)`, current item accessible
1314+
// from more place then parent
1315+
"pub(crate)"
1316+
}
1317+
}
1318+
// parent is `pub`
1319+
ty::Visibility::Public => {
1320+
// current item may be used from anywhere in the crate
1321+
"pub(crate)"
1322+
}
1323+
},
1324+
None => "pub(crate)",
1325+
};
13011326
if vis_span.from_expansion() {
13021327
applicability = Applicability::MaybeIncorrect;
13031328
}
13041329
let def_span = cx.tcx.def_span(def_id);
13051330
cx.emit_span_lint(UNREACHABLE_PUB, def_span, BuiltinUnreachablePub {
13061331
what,
1332+
new_vis,
13071333
suggestion: (vis_span, applicability),
13081334
help: exportable,
13091335
});

compiler/rustc_lint/src/lints.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,8 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
254254
#[diag(lint_builtin_unreachable_pub)]
255255
pub(crate) struct BuiltinUnreachablePub<'a> {
256256
pub what: &'a str,
257-
#[suggestion(code = "pub(crate)")]
257+
pub new_vis: &'a str,
258+
#[suggestion(code = "{new_vis}")]
258259
pub suggestion: (Span, Applicability),
259260
#[help]
260261
pub help: bool,

tests/ui/lint/issue-103317.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#[warn(unreachable_pub)]
55
mod inner {
66
#[allow(unused)]
7-
pub(crate) enum T {
7+
pub(super) enum T {
88
//~^ WARN unreachable `pub` item
99
A(u8),
1010
X { a: f32, b: () },

tests/ui/lint/issue-103317.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ warning: unreachable `pub` item
44
LL | pub enum T {
55
| ---^^^^^^^
66
| |
7-
| help: consider restricting its visibility: `pub(crate)`
7+
| help: consider restricting its visibility: `pub(super)`
88
|
99
= help: or consider exporting it for use by other crates
1010
note: the lint level is defined here

tests/ui/lint/unreachable_pub.fixed

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//@ check-pass
2+
//@ run-rustfix
3+
4+
#![allow(unused)]
5+
#![warn(unreachable_pub)]
6+
7+
mod private_mod {
8+
// non-leaked `pub` items in private module should be linted
9+
pub(super) use std::fmt; //~ WARNING unreachable_pub
10+
pub(super) use std::env::{Args}; // braced-use has different item spans than unbraced
11+
//~^ WARNING unreachable_pub
12+
13+
// we lint on struct definition
14+
pub(super) struct Hydrogen { //~ WARNING unreachable_pub
15+
// but not on fields, even if they are `pub` as putting `pub(crate)`
16+
// it would clutter the source code for little value
17+
pub neutrons: usize,
18+
pub(crate) electrons: usize
19+
}
20+
pub(crate) struct Calcium {
21+
pub neutrons: usize,
22+
}
23+
impl Hydrogen {
24+
// impls, too
25+
pub(super) fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub
26+
pub(crate) fn count_electrons(&self) -> usize { self.electrons }
27+
}
28+
impl Clone for Hydrogen {
29+
fn clone(&self) -> Hydrogen {
30+
Hydrogen { neutrons: self.neutrons, electrons: self.electrons }
31+
}
32+
}
33+
34+
pub(super) enum Helium {} //~ WARNING unreachable_pub
35+
pub(super) union Lithium { c1: usize, c2: u8 } //~ WARNING unreachable_pub
36+
pub(super) fn beryllium() {} //~ WARNING unreachable_pub
37+
pub(super) trait Boron {} //~ WARNING unreachable_pub
38+
pub(super) const CARBON: usize = 1; //~ WARNING unreachable_pub
39+
pub(super) static NITROGEN: usize = 2; //~ WARNING unreachable_pub
40+
pub(super) type Oxygen = bool; //~ WARNING unreachable_pub
41+
42+
macro_rules! define_empty_struct_with_visibility {
43+
($visibility: vis, $name: ident) => { $visibility struct $name {} }
44+
//~^ WARNING unreachable_pub
45+
}
46+
define_empty_struct_with_visibility!(pub(super), Fluorine);
47+
48+
extern "C" {
49+
pub(super) fn catalyze() -> bool; //~ WARNING unreachable_pub
50+
}
51+
52+
mod private_in_private {
53+
pub(super) enum Helium {} //~ WARNING unreachable_pub
54+
pub(super) fn beryllium() {} //~ WARNING unreachable_pub
55+
}
56+
57+
pub(crate) mod crate_in_private {
58+
pub(crate) const CARBON: usize = 1; //~ WARNING unreachable_pub
59+
}
60+
61+
pub(super) mod pub_in_private { //~ WARNING unreachable_pub
62+
pub(crate) static NITROGEN: usize = 2; //~ WARNING unreachable_pub
63+
}
64+
65+
// items leaked through signatures (see `get_neon` below) are OK
66+
pub struct Neon {}
67+
68+
// crate-visible items are OK
69+
pub(crate) struct Sodium {}
70+
}
71+
72+
pub mod public_mod {
73+
// module is public: these are OK, too
74+
pub struct Magnesium {}
75+
pub(crate) struct Aluminum {}
76+
}
77+
78+
pub fn get_neon() -> private_mod::Neon {
79+
private_mod::Neon {}
80+
}
81+
82+
fn main() {
83+
let _ = get_neon();
84+
let _ = private_mod::beryllium();
85+
let _ = private_mod::crate_in_private::CARBON;
86+
let _ = private_mod::pub_in_private::NITROGEN;
87+
}

tests/ui/lint/unreachable_pub.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//@ check-pass
2+
//@ run-rustfix
23

34
#![allow(unused)]
45
#![warn(unreachable_pub)]
@@ -48,6 +49,19 @@ mod private_mod {
4849
pub fn catalyze() -> bool; //~ WARNING unreachable_pub
4950
}
5051

52+
mod private_in_private {
53+
pub enum Helium {} //~ WARNING unreachable_pub
54+
pub fn beryllium() {} //~ WARNING unreachable_pub
55+
}
56+
57+
pub(crate) mod crate_in_private {
58+
pub const CARBON: usize = 1; //~ WARNING unreachable_pub
59+
}
60+
61+
pub mod pub_in_private { //~ WARNING unreachable_pub
62+
pub static NITROGEN: usize = 2; //~ WARNING unreachable_pub
63+
}
64+
5165
// items leaked through signatures (see `get_neon` below) are OK
5266
pub struct Neon {}
5367

@@ -67,4 +81,7 @@ pub fn get_neon() -> private_mod::Neon {
6781

6882
fn main() {
6983
let _ = get_neon();
84+
let _ = private_mod::beryllium();
85+
let _ = private_mod::crate_in_private::CARBON;
86+
let _ = private_mod::pub_in_private::NITROGEN;
7087
}

0 commit comments

Comments
 (0)