Skip to content

Commit

Permalink
private no-mangle lints: help hint note if visibility modifier is pub
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
zackmdavis committed Jul 1, 2018
1 parent 5330747 commit 8d1cbb0
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 32 deletions.
11 changes: 7 additions & 4 deletions src/librustc_lint/builtin.rs
Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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 {
Expand All @@ -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();
}
}
Expand Down
28 changes: 21 additions & 7 deletions src/test/ui/lint/suggestions.rs
Expand Up @@ -13,33 +13,41 @@
#![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
// item is already `pub` (but triggered the lint because, e.g., it's in a
// 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 {
Expand All @@ -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);
}
Expand Down
47 changes: 26 additions & 21 deletions src/test/ui/lint/suggestions.stderr
@@ -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
Expand All @@ -11,17 +11,17 @@ 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
|
= 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`
Expand All @@ -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
| _____________^
Expand All @@ -47,83 +47,88 @@ 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`
|
= 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`
|
= 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`
|
= 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;
| ----------^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| 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() {}
| ----------^^^^^^^^^^^^^^^^^^^
| |
| 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
Expand Down

0 comments on commit 8d1cbb0

Please sign in to comment.