]> git.lizzy.rs Git - rust.git/commitdiff
private no-mangle lints: issue suggestion for restricted visibility
authorZack M. Davis <code@zackmdavis.net>
Thu, 28 Jun 2018 05:30:23 +0000 (22:30 -0700)
committerZack M. Davis <code@zackmdavis.net>
Sun, 1 Jul 2018 05:47:47 +0000 (22:47 -0700)
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.

src/librustc_lint/builtin.rs
src/test/ui/lint/suggestions.rs
src/test/ui/lint/suggestions.stderr

index a9ee1c8f17686003dcc19a3454ce9740934a9d66..f4159002eb3859acb5adbd8b86672957c1f329ee 100644 (file)
@@ -1177,6 +1177,23 @@ fn get_lints(&self) -> LintArray {
 
 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 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                     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 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
             }
             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") {
index e35675eacd835cc88f1d7f7e7e25165ec751f7c0..6c767bca74ae2207f7571291723a6525657440fe 100644 (file)
@@ -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 {
index 84a2e4a91eccf736e98d165f04e2a8e74146ef38..adb4b8eb67d570d2c7050211385848819e7f2c28 100644 (file)
@@ -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
    |                       ------------^^^^^^^^^^^^