Skip to content

Commit

Permalink
private no-mangle lints: issue suggestion for restricted visibility
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
zackmdavis committed Jul 1, 2018
1 parent 104985b commit 5330747
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 23 deletions.
41 changes: 24 additions & 17 deletions src/librustc_lint/builtin.rs
Expand Up @@ -1177,6 +1177,23 @@ 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 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 {
hir::ItemFn(.., ref generics, _) => {
if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, "no_mangle") {
Expand All @@ -1186,12 +1203,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);
let insertion_span = it.span.shrink_to_lo();
if it.vis.node == hir::VisibilityInherited {
err.span_suggestion(insertion_span,
"try making it public",
"pub ".to_owned());
}
suggest_make_pub(&it.vis, &mut err);
err.emit();
}
for param in &generics.params {
Expand All @@ -1214,17 +1226,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
}
hir::ItemStatic(..) => {
if attr::contains_name(&it.attrs, "no_mangle") &&
!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);
let insertion_span = it.span.shrink_to_lo();
if it.vis.node == hir::VisibilityInherited {
err.span_suggestion(insertion_span,
"try making it public",
"pub ".to_owned());
}
err.emit();
}
!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);
err.emit();
}
}
hir::ItemConst(..) => {
if attr::contains_name(&it.attrs, "no_mangle") {
Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/lint/suggestions.rs
Expand Up @@ -34,6 +34,12 @@ mod badlands {
//~^ WARN static is marked
#[no_mangle] pub fn val_jean() {}
//~^ 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 {
Expand Down
28 changes: 22 additions & 6 deletions src/test/ui/lint/suggestions.stderr
@@ -1,5 +1,5 @@
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
| ^^^ help: remove these parentheses
Expand All @@ -11,15 +11,15 @@ 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:43:1
--> $DIR/suggestions.rs:49: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:48:13
--> $DIR/suggestions.rs:54:13
|
LL | let mut a = (1); // should suggest no `mut`, no parens
| ----^
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:52:13
--> $DIR/suggestions.rs:58:13
|
LL | let mut
| _____________^
Expand Down Expand Up @@ -96,16 +96,32 @@ warning: function is marked #[no_mangle], but not exported
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 { ... }`
--> $DIR/suggestions.rs:46:5
--> $DIR/suggestions.rs:52:5
|
LL | while true { // should suggest `loop`
| ^^^^^^^^^^ help: use `loop`
|
= note: #[warn(while_true)] on by default

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
| ------------^^^^^^^^^^^^
Expand Down

0 comments on commit 5330747

Please sign in to comment.