private no-mangle lints: help hint note if visibility modifier is `pub`

If the item is `pub`, one imagines users being confused as to why it's
not reachable/exported; a code suggestion is beyond our local knowledge
here, but we can at least offer a prose hint. (Thanks to Vadim
Petrochenkov for shooting down the present author's original bad idea
for the note text.)

While we're here, use proper HELP expectations instead of ad hoc
comments to communicate (and now, enforce) the expected suggestions in
test/ui/lint/suggestions.rs.
This commit is contained in:
Zack M. Davis 2018-06-27 22:50:24 -07:00
parent 53307473fd
commit 8d1cbb018e
3 changed files with 54 additions and 32 deletions

View File

@ -1177,7 +1177,7 @@ impl LintPass for InvalidNoMangleItems {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
let suggest_make_pub = |vis: &hir::Visibility, err: &mut DiagnosticBuilder| {
let suggest_export = |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
@ -1187,7 +1187,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
hir::VisibilityCrate(_) => {
Some("pub".to_owned())
},
hir::VisibilityPublic => None
hir::VisibilityPublic => {
err.help("try exporting the item with a `pub use` statement");
None
}
};
if let Some(replacement) = suggestion {
err.span_suggestion(vis.span, "try making it public", replacement);
@ -1203,7 +1206,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
if !cx.access_levels.is_reachable(it.id) {
let msg = "function is marked #[no_mangle], but not exported";
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
suggest_make_pub(&it.vis, &mut err);
suggest_export(&it.vis, &mut err);
err.emit();
}
for param in &generics.params {
@ -1229,7 +1232,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
!cx.access_levels.is_reachable(it.id) {
let msg = "static is marked #[no_mangle], but not exported";
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
suggest_make_pub(&it.vis, &mut err);
suggest_export(&it.vis, &mut err);
err.emit();
}
}

View File

@ -13,18 +13,22 @@
#![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
#![feature(no_debug)]
#[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
#[no_mangle] static SHENZHOU: usize = 1;
//~^ WARN static is marked #[no_mangle]
#[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
//~| HELP try making it public
#[no_mangle] const DISCOVERY: usize = 1;
//~^ ERROR const items should never be #[no_mangle]
//~| HELP try a static value
#[no_mangle] // should suggest removal (generics can't be no-mangle)
#[no_mangle]
//~^ HELP remove this attribute
pub fn defiant<T>(_t: T) {}
//~^ WARN functions generic over types must be mangled
#[no_mangle]
fn rio_grande() {} // should suggest `pub`
fn rio_grande() {}
//~^ WARN function is marked
//~| HELP try making it public
mod badlands {
// The private-no-mangle lints shouldn't suggest inserting `pub` when the
@ -32,14 +36,18 @@ mod badlands {
// private module). (Issue #47383)
#[no_mangle] pub static DAUNTLESS: bool = true;
//~^ WARN static is marked
//~| HELP try exporting the item with a `pub use` statement
#[no_mangle] pub fn val_jean() {}
//~^ WARN function is marked
//~| HELP try exporting the item with a `pub use` statement
// ... but we can suggest just-`pub` instead of restricted
#[no_mangle] pub(crate) static VETAR: bool = true;
//~^ WARN static is marked
//~| HELP try making it public
#[no_mangle] pub(crate) fn crossfield() {}
//~^ WARN function is marked
//~| HELP try making it public
}
struct Equinox {
@ -48,20 +56,26 @@ struct Equinox {
#[no_debug] // should suggest removal of deprecated attribute
//~^ WARN deprecated
//~| HELP remove this attribute
fn main() {
while true { // should suggest `loop`
while true {
//~^ WARN denote infinite loops
let mut a = (1); // should suggest no `mut`, no parens
//~| HELP use `loop`
let mut a = (1);
//~^ WARN does not need to be mutable
//~| HELP remove this `mut`
//~| WARN unnecessary parentheses
//~| HELP remove these parentheses
// the line after `mut` has a `\t` at the beginning, this is on purpose
let mut
b = 1;
//~^^ WARN does not need to be mutable
//~| HELP remove this `mut`
let d = Equinox { warp_factor: 9.975 };
match d {
Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
Equinox { warp_factor: warp_factor } => {}
//~^ WARN this pattern is redundant
//~| HELP remove this
}
println!("{} {}", a, b);
}

View File

@ -1,7 +1,7 @@
warning: unnecessary parentheses around assigned value
--> $DIR/suggestions.rs:54:21
--> $DIR/suggestions.rs:64:21
|
LL | let mut a = (1); // should suggest no `mut`, no parens
LL | let mut a = (1);
| ^^^ help: remove these parentheses
|
note: lint level defined here
@ -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
--> $DIR/suggestions.rs:49:1
--> $DIR/suggestions.rs:57:1
|
LL | #[no_debug] // should suggest removal of deprecated attribute
| ^^^^^^^^^^^ help: remove this attribute
@ -19,9 +19,9 @@ LL | #[no_debug] // should suggest removal of deprecated attribute
= note: #[warn(deprecated)] on by default
warning: variable does not need to be mutable
--> $DIR/suggestions.rs:54:13
--> $DIR/suggestions.rs:64:13
|
LL | let mut a = (1); // should suggest no `mut`, no parens
LL | let mut a = (1);
| ----^
| |
| help: remove this `mut`
@ -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
--> $DIR/suggestions.rs:58:13
--> $DIR/suggestions.rs:70:13
|
LL | let mut
| _____________^
@ -47,7 +47,7 @@ LL | || b = 1;
warning: static is marked #[no_mangle], but not exported
--> $DIR/suggestions.rs:16:14
|
LL | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
LL | #[no_mangle] static SHENZHOU: usize = 1;
| -^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| help: try making it public: `pub`
@ -55,9 +55,9 @@ LL | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
= note: #[warn(private_no_mangle_statics)] on by default
error: const items should never be #[no_mangle]
--> $DIR/suggestions.rs:18:14
--> $DIR/suggestions.rs:19:14
|
LL | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
LL | #[no_mangle] const DISCOVERY: usize = 1;
| -----^^^^^^^^^^^^^^^^^^^^^^
| |
| help: try a static value: `pub static`
@ -65,19 +65,20 @@ LL | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rat
= note: #[deny(no_mangle_const_items)] on by default
warning: functions generic over types must be mangled
--> $DIR/suggestions.rs:22:1
--> $DIR/suggestions.rs:25:1
|
LL | #[no_mangle] // should suggest removal (generics can't be no-mangle)
LL | #[no_mangle]
| ------------ help: remove this attribute
LL | //~^ HELP remove this attribute
LL | pub fn defiant<T>(_t: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(no_mangle_generic_items)] on by default
warning: function is marked #[no_mangle], but not exported
--> $DIR/suggestions.rs:26:1
--> $DIR/suggestions.rs:29:1
|
LL | fn rio_grande() {} // should suggest `pub`
LL | fn rio_grande() {}
| -^^^^^^^^^^^^^^^^^
| |
| help: try making it public: `pub`
@ -85,19 +86,23 @@ LL | fn rio_grande() {} // should suggest `pub`
= note: #[warn(private_no_mangle_fns)] on by default
warning: static is marked #[no_mangle], but not exported
--> $DIR/suggestions.rs:33:18
--> $DIR/suggestions.rs:37:18
|
LL | #[no_mangle] pub static DAUNTLESS: bool = true;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: try exporting the item with a `pub use` statement
warning: function is marked #[no_mangle], but not exported
--> $DIR/suggestions.rs:35:18
--> $DIR/suggestions.rs:40:18
|
LL | #[no_mangle] pub fn val_jean() {}
| ^^^^^^^^^^^^^^^^^^^^
|
= help: try exporting the item with a `pub use` statement
warning: static is marked #[no_mangle], but not exported
--> $DIR/suggestions.rs:39:18
--> $DIR/suggestions.rs:45:18
|
LL | #[no_mangle] pub(crate) static VETAR: bool = true;
| ----------^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -105,7 +110,7 @@ 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
--> $DIR/suggestions.rs:48:18
|
LL | #[no_mangle] pub(crate) fn crossfield() {}
| ----------^^^^^^^^^^^^^^^^^^^
@ -113,17 +118,17 @@ LL | #[no_mangle] pub(crate) fn crossfield() {}
| help: try making it public: `pub`
warning: denote infinite loops with `loop { ... }`
--> $DIR/suggestions.rs:52:5
--> $DIR/suggestions.rs:61:5
|
LL | while true { // should suggest `loop`
LL | while true {
| ^^^^^^^^^^ help: use `loop`
|
= note: #[warn(while_true)] on by default
warning: the `warp_factor:` in this pattern is redundant
--> $DIR/suggestions.rs:63:23
--> $DIR/suggestions.rs:76:23
|
LL | Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
LL | Equinox { warp_factor: warp_factor } => {}
| ------------^^^^^^^^^^^^
| |
| help: remove this