private no-mangle lints: issue suggestion for restricted visibility
This is probably quite a lot less likely to come up in practice than the "inherited" (no visibility keyword) case, but now that we have visibility spans in the HIR, we can do this, and it presumably doesn't hurt to be exhaustive. (Who can say but that the attention to detail just might knock someone's socks off, someday, somewhere?) This is inspired by #47383.
This commit is contained in:
parent
104985b827
commit
53307473fd
3 changed files with 52 additions and 23 deletions
|
@ -1177,6 +1177,23 @@ impl LintPass for InvalidNoMangleItems {
|
||||||
|
|
||||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
|
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
|
||||||
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
|
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
|
||||||
|
let suggest_make_pub = |vis: &hir::Visibility, err: &mut DiagnosticBuilder| {
|
||||||
|
let suggestion = match vis.node {
|
||||||
|
hir::VisibilityInherited => {
|
||||||
|
// inherited visibility is empty span at item start; need an extra space
|
||||||
|
Some("pub ".to_owned())
|
||||||
|
},
|
||||||
|
hir::VisibilityRestricted { .. } |
|
||||||
|
hir::VisibilityCrate(_) => {
|
||||||
|
Some("pub".to_owned())
|
||||||
|
},
|
||||||
|
hir::VisibilityPublic => None
|
||||||
|
};
|
||||||
|
if let Some(replacement) = suggestion {
|
||||||
|
err.span_suggestion(vis.span, "try making it public", replacement);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
match it.node {
|
match it.node {
|
||||||
hir::ItemFn(.., ref generics, _) => {
|
hir::ItemFn(.., ref generics, _) => {
|
||||||
if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, "no_mangle") {
|
if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, "no_mangle") {
|
||||||
|
@ -1186,12 +1203,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
|
||||||
if !cx.access_levels.is_reachable(it.id) {
|
if !cx.access_levels.is_reachable(it.id) {
|
||||||
let msg = "function is marked #[no_mangle], but not exported";
|
let msg = "function is marked #[no_mangle], but not exported";
|
||||||
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
|
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
|
||||||
let insertion_span = it.span.shrink_to_lo();
|
suggest_make_pub(&it.vis, &mut err);
|
||||||
if it.vis.node == hir::VisibilityInherited {
|
|
||||||
err.span_suggestion(insertion_span,
|
|
||||||
"try making it public",
|
|
||||||
"pub ".to_owned());
|
|
||||||
}
|
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
|
@ -1214,17 +1226,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
|
||||||
}
|
}
|
||||||
hir::ItemStatic(..) => {
|
hir::ItemStatic(..) => {
|
||||||
if attr::contains_name(&it.attrs, "no_mangle") &&
|
if attr::contains_name(&it.attrs, "no_mangle") &&
|
||||||
!cx.access_levels.is_reachable(it.id) {
|
!cx.access_levels.is_reachable(it.id) {
|
||||||
let msg = "static is marked #[no_mangle], but not exported";
|
let msg = "static is marked #[no_mangle], but not exported";
|
||||||
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
|
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
|
||||||
let insertion_span = it.span.shrink_to_lo();
|
suggest_make_pub(&it.vis, &mut err);
|
||||||
if it.vis.node == hir::VisibilityInherited {
|
err.emit();
|
||||||
err.span_suggestion(insertion_span,
|
}
|
||||||
"try making it public",
|
|
||||||
"pub ".to_owned());
|
|
||||||
}
|
|
||||||
err.emit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
hir::ItemConst(..) => {
|
hir::ItemConst(..) => {
|
||||||
if attr::contains_name(&it.attrs, "no_mangle") {
|
if attr::contains_name(&it.attrs, "no_mangle") {
|
||||||
|
|
|
@ -34,6 +34,12 @@ mod badlands {
|
||||||
//~^ WARN static is marked
|
//~^ WARN static is marked
|
||||||
#[no_mangle] pub fn val_jean() {}
|
#[no_mangle] pub fn val_jean() {}
|
||||||
//~^ WARN function is marked
|
//~^ WARN function is marked
|
||||||
|
|
||||||
|
// ... but we can suggest just-`pub` instead of restricted
|
||||||
|
#[no_mangle] pub(crate) static VETAR: bool = true;
|
||||||
|
//~^ WARN static is marked
|
||||||
|
#[no_mangle] pub(crate) fn crossfield() {}
|
||||||
|
//~^ WARN function is marked
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Equinox {
|
struct Equinox {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
warning: unnecessary parentheses around assigned value
|
warning: unnecessary parentheses around assigned value
|
||||||
--> $DIR/suggestions.rs:48:21
|
--> $DIR/suggestions.rs:54:21
|
||||||
|
|
|
|
||||||
LL | let mut a = (1); // should suggest no `mut`, no parens
|
LL | let mut a = (1); // should suggest no `mut`, no parens
|
||||||
| ^^^ help: remove these parentheses
|
| ^^^ help: remove these parentheses
|
||||||
|
@ -11,7 +11,7 @@ LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issu
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
|
warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
|
||||||
--> $DIR/suggestions.rs:43:1
|
--> $DIR/suggestions.rs:49:1
|
||||||
|
|
|
|
||||||
LL | #[no_debug] // should suggest removal of deprecated attribute
|
LL | #[no_debug] // should suggest removal of deprecated attribute
|
||||||
| ^^^^^^^^^^^ help: remove this attribute
|
| ^^^^^^^^^^^ help: remove this attribute
|
||||||
|
@ -19,7 +19,7 @@ LL | #[no_debug] // should suggest removal of deprecated attribute
|
||||||
= note: #[warn(deprecated)] on by default
|
= note: #[warn(deprecated)] on by default
|
||||||
|
|
||||||
warning: variable does not need to be mutable
|
warning: variable does not need to be mutable
|
||||||
--> $DIR/suggestions.rs:48:13
|
--> $DIR/suggestions.rs:54:13
|
||||||
|
|
|
|
||||||
LL | let mut a = (1); // should suggest no `mut`, no parens
|
LL | let mut a = (1); // should suggest no `mut`, no parens
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -33,7 +33,7 @@ LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issu
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
warning: variable does not need to be mutable
|
warning: variable does not need to be mutable
|
||||||
--> $DIR/suggestions.rs:52:13
|
--> $DIR/suggestions.rs:58:13
|
||||||
|
|
|
|
||||||
LL | let mut
|
LL | let mut
|
||||||
| _____________^
|
| _____________^
|
||||||
|
@ -96,8 +96,24 @@ warning: function is marked #[no_mangle], but not exported
|
||||||
LL | #[no_mangle] pub fn val_jean() {}
|
LL | #[no_mangle] pub fn val_jean() {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: static is marked #[no_mangle], but not exported
|
||||||
|
--> $DIR/suggestions.rs:39:18
|
||||||
|
|
|
||||||
|
LL | #[no_mangle] pub(crate) static VETAR: bool = true;
|
||||||
|
| ----------^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: try making it public: `pub`
|
||||||
|
|
||||||
|
warning: function is marked #[no_mangle], but not exported
|
||||||
|
--> $DIR/suggestions.rs:41:18
|
||||||
|
|
|
||||||
|
LL | #[no_mangle] pub(crate) fn crossfield() {}
|
||||||
|
| ----------^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: try making it public: `pub`
|
||||||
|
|
||||||
warning: denote infinite loops with `loop { ... }`
|
warning: denote infinite loops with `loop { ... }`
|
||||||
--> $DIR/suggestions.rs:46:5
|
--> $DIR/suggestions.rs:52:5
|
||||||
|
|
|
|
||||||
LL | while true { // should suggest `loop`
|
LL | while true { // should suggest `loop`
|
||||||
| ^^^^^^^^^^ help: use `loop`
|
| ^^^^^^^^^^ help: use `loop`
|
||||||
|
@ -105,7 +121,7 @@ LL | while true { // should suggest `loop`
|
||||||
= note: #[warn(while_true)] on by default
|
= note: #[warn(while_true)] on by default
|
||||||
|
|
||||||
warning: the `warp_factor:` in this pattern is redundant
|
warning: the `warp_factor:` in this pattern is redundant
|
||||||
--> $DIR/suggestions.rs:57:23
|
--> $DIR/suggestions.rs:63:23
|
||||||
|
|
|
|
||||||
LL | Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
|
LL | Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
|
||||||
| ------------^^^^^^^^^^^^
|
| ------------^^^^^^^^^^^^
|
||||||
|
|
Loading…
Add table
Reference in a new issue