Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefer pub(super) in unreachable_pub lint suggestion #132426

Merged
merged 1 commit into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1298,12 +1298,30 @@ impl UnreachablePub {
let mut applicability = Applicability::MachineApplicable;
if cx.tcx.visibility(def_id).is_public() && !cx.effective_visibilities.is_reachable(def_id)
{
// prefer suggesting `pub(super)` instead of `pub(crate)` when possible,
// except when `pub(super) == pub(crate)`
let new_vis = if let Some(ty::Visibility::Restricted(restricted_did)) =
cx.effective_visibilities.effective_vis(def_id).map(|effective_vis| {
effective_vis.at_level(rustc_middle::middle::privacy::Level::Reachable)
})
&& let parent_parent = cx.tcx.parent_module_from_def_id(
cx.tcx.parent_module_from_def_id(def_id.into()).into(),
)
&& *restricted_did == parent_parent.to_local_def_id()
&& !restricted_did.to_def_id().is_crate_root()
{
"pub(super)"
} else {
"pub(crate)"
};

if vis_span.from_expansion() {
applicability = Applicability::MaybeIncorrect;
}
let def_span = cx.tcx.def_span(def_id);
cx.emit_span_lint(UNREACHABLE_PUB, def_span, BuiltinUnreachablePub {
what,
new_vis,
suggestion: (vis_span, applicability),
help: exportable,
});
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,8 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
#[diag(lint_builtin_unreachable_pub)]
pub(crate) struct BuiltinUnreachablePub<'a> {
pub what: &'a str,
#[suggestion(code = "pub(crate)")]
pub new_vis: &'a str,
#[suggestion(code = "{new_vis}")]
pub suggestion: (Span, Applicability),
#[help]
pub help: bool,
Expand Down
116 changes: 116 additions & 0 deletions tests/ui/lint/unreachable_pub.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//@ check-pass
//@ edition: 2018
//@ run-rustfix

#![allow(unused)]
#![warn(unreachable_pub)]

mod private_mod {
// non-leaked `pub` items in private module should be linted
pub(crate) use std::fmt; //~ WARNING unreachable_pub
pub(crate) use std::env::{Args}; // braced-use has different item spans than unbraced
//~^ WARNING unreachable_pub

// we lint on struct definition
pub(crate) struct Hydrogen { //~ WARNING unreachable_pub
// but not on fields, even if they are `pub` as putting `pub(crate)`
// it would clutter the source code for little value
pub neutrons: usize,
pub(crate) electrons: usize
}
pub(crate) struct Calcium {
pub neutrons: usize,
}
impl Hydrogen {
// impls, too
pub(crate) fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub
pub(crate) fn count_electrons(&self) -> usize { self.electrons }
}
impl Clone for Hydrogen {
fn clone(&self) -> Hydrogen {
Hydrogen { neutrons: self.neutrons, electrons: self.electrons }
}
}

pub(crate) enum Helium {} //~ WARNING unreachable_pub
pub(crate) union Lithium { c1: usize, c2: u8 } //~ WARNING unreachable_pub
pub(crate) fn beryllium() {} //~ WARNING unreachable_pub
pub(crate) trait Boron {} //~ WARNING unreachable_pub
pub(crate) const CARBON: usize = 1; //~ WARNING unreachable_pub
pub(crate) static NITROGEN: usize = 2; //~ WARNING unreachable_pub
pub(crate) type Oxygen = bool; //~ WARNING unreachable_pub

macro_rules! define_empty_struct_with_visibility {
($visibility: vis, $name: ident) => { $visibility struct $name {} }
//~^ WARNING unreachable_pub
}
define_empty_struct_with_visibility!(pub(crate), Fluorine);

extern "C" {
pub(crate) fn catalyze() -> bool; //~ WARNING unreachable_pub
}

mod private_in_private {
pub(super) enum Helium {} //~ WARNING unreachable_pub
pub(super) fn beryllium() {} //~ WARNING unreachable_pub
}

pub(crate) mod crate_in_private {
pub(crate) const CARBON: usize = 1; //~ WARNING unreachable_pub
}

pub(crate) mod pub_in_private { //~ WARNING unreachable_pub
pub(crate) static NITROGEN: usize = 2; //~ WARNING unreachable_pub
}

fn foo() {
const {
pub(crate) struct Foo; //~ WARNING unreachable_pub
};
}

enum Weird {
Variant = {
pub(crate) struct Foo; //~ WARNING unreachable_pub

mod tmp {
pub(crate) struct Bar; //~ WARNING unreachable_pub
}

let _ = tmp::Bar;

0
},
}

pub(crate) use fpu_precision::set_precision; //~ WARNING unreachable_pub

mod fpu_precision {
pub(crate) fn set_precision<T>() {} //~ WARNING unreachable_pub
pub(super) fn set_micro_precision<T>() {} //~ WARNING unreachable_pub
}

// items leaked through signatures (see `get_neon` below) are OK
pub struct Neon {}

// crate-visible items are OK
pub(crate) struct Sodium {}
}

pub mod public_mod {
// module is public: these are OK, too
pub struct Magnesium {}
pub(crate) struct Aluminum {}
}

pub fn get_neon() -> private_mod::Neon {
private_mod::Neon {}
}

fn main() {
let _ = get_neon();
let _ = private_mod::beryllium();
let _ = private_mod::crate_in_private::CARBON;
let _ = private_mod::pub_in_private::NITROGEN;
let _ = unsafe { private_mod::catalyze() };
}
46 changes: 46 additions & 0 deletions tests/ui/lint/unreachable_pub.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//@ check-pass
//@ edition: 2018
//@ run-rustfix

#![allow(unused)]
#![warn(unreachable_pub)]
Expand Down Expand Up @@ -48,6 +50,46 @@ mod private_mod {
pub fn catalyze() -> bool; //~ WARNING unreachable_pub
}

mod private_in_private {
pub enum Helium {} //~ WARNING unreachable_pub
pub fn beryllium() {} //~ WARNING unreachable_pub
}

pub(crate) mod crate_in_private {
pub const CARBON: usize = 1; //~ WARNING unreachable_pub
}

pub mod pub_in_private { //~ WARNING unreachable_pub
pub static NITROGEN: usize = 2; //~ WARNING unreachable_pub
}

fn foo() {
const {
pub struct Foo; //~ WARNING unreachable_pub
};
}

enum Weird {
Variant = {
pub struct Foo; //~ WARNING unreachable_pub

mod tmp {
pub struct Bar; //~ WARNING unreachable_pub
}

let _ = tmp::Bar;

0
},
}

pub use fpu_precision::set_precision; //~ WARNING unreachable_pub

mod fpu_precision {
pub fn set_precision<T>() {} //~ WARNING unreachable_pub
pub fn set_micro_precision<T>() {} //~ WARNING unreachable_pub
}

// items leaked through signatures (see `get_neon` below) are OK
pub struct Neon {}

Expand All @@ -67,4 +109,8 @@ pub fn get_neon() -> private_mod::Neon {

fn main() {
let _ = get_neon();
let _ = private_mod::beryllium();
let _ = private_mod::crate_in_private::CARBON;
let _ = private_mod::pub_in_private::NITROGEN;
let _ = unsafe { private_mod::catalyze() };
}
Loading
Loading