diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index a9ee1c8f1768..f4159002eb38 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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") { @@ -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 { @@ -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") { diff --git a/src/test/ui/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs index e35675eacd83..6c767bca74ae 100644 --- a/src/test/ui/lint/suggestions.rs +++ b/src/test/ui/lint/suggestions.rs @@ -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 { diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index 84a2e4a91ecc..adb4b8eb67d5 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/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 @@ -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:43:1 + --> $DIR/suggestions.rs:49:1 | LL | #[no_debug] // should suggest removal of deprecated attribute | ^^^^^^^^^^^ help: remove this attribute @@ -19,7 +19,7 @@ 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:48:13 + --> $DIR/suggestions.rs:54:13 | 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 - --> $DIR/suggestions.rs:52:13 + --> $DIR/suggestions.rs:58:13 | LL | let mut | _____________^ @@ -96,8 +96,24 @@ 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` @@ -105,7 +121,7 @@ LL | while true { // should suggest `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 | ------------^^^^^^^^^^^^