]> git.lizzy.rs Git - rust.git/commitdiff
structured suggestions for unused-lifetimes lint
authorZack M. Davis <code@zackmdavis.net>
Sun, 30 Sep 2018 04:25:41 +0000 (21:25 -0700)
committerZack M. Davis <code@zackmdavis.net>
Mon, 8 Oct 2018 02:17:39 +0000 (19:17 -0700)
src/librustc/middle/resolve_lifetime.rs
src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed [new file with mode: 0644]
src/test/ui/single-use-lifetime/zero-uses-in-fn.rs
src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr
src/test/ui/single-use-lifetime/zero-uses-in-impl.rs
src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr

index a10b387672ad6311a4da7e7497dbbcd17a46bd7b..53bfee4ae24bb9d05a7ab9fe51440196e602ec19 100644 (file)
@@ -19,9 +19,9 @@
 use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use hir::map::Map;
 use hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, ParamName, Node};
-use ty::{self, TyCtxt, GenericParamDefKind};
+use ty::{self, TyCtxt, DefIdTree, GenericParamDefKind};
 
-use errors::DiagnosticBuilder;
+use errors::{Applicability, DiagnosticBuilder};
 use rustc::lint;
 use rustc_data_structures::sync::Lrc;
 use session::Session;
@@ -1468,12 +1468,61 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
                         _ => None,
                     } {
                         debug!("id ={:?} span = {:?} name = {:?}", node_id, span, name);
-                        self.tcx.struct_span_lint_node(
+                        let mut err = self.tcx.struct_span_lint_node(
                             lint::builtin::UNUSED_LIFETIMES,
                             id,
                             span,
                             &format!("lifetime parameter `{}` never used", name)
-                        ).emit();
+                        );
+                        if let Some(parent_def_id) = self.tcx.parent(def_id) {
+                            if let Some(node_id) = self.tcx.hir.as_local_node_id(parent_def_id) {
+                                if let Some(Node::Item(hir_item)) = self.tcx.hir.find(node_id) {
+                                    match hir_item.node {
+                                        hir::ItemKind::Fn(_, _, ref generics, _) |
+                                        hir::ItemKind::Impl(_, _, _, ref generics, _, _, _) => {
+                                            let unused_lt_span = if generics.params.len() == 1 {
+                                                // if sole lifetime, remove the `<>` brackets
+                                                Some(generics.span)
+                                            } else {
+                                                generics.params.iter().enumerate()
+                                                    .find_map(|(i, param)| {
+                                                        if param.name.ident() == name {
+                                                            // We also want to delete a leading or
+                                                            // trailing comma as appropriate
+                                                            if i >= generics.params.len() - 1 {
+                                                                Some(
+                                                                    generics.params[i-1]
+                                                                        .span.shrink_to_hi()
+                                                                        .to(param.span)
+                                                                )
+                                                            } else {
+                                                                Some(
+                                                                    param.span.to(
+                                                                        generics.params[i+1]
+                                                                            .span.shrink_to_lo()
+                                                                    )
+                                                                )
+                                                            }
+                                                        } else {
+                                                            None
+                                                        }
+                                                    })
+                                            };
+                                            if let Some(span) = unused_lt_span {
+                                                err.span_suggestion_with_applicability(
+                                                    span,
+                                                    "remove it",
+                                                    String::new(),
+                                                    Applicability::MachineApplicable
+                                                );
+                                            }
+                                        },
+                                        _ => {}
+                                    }
+                                }
+                            }
+                        }
+                        err.emit();
                     }
                 }
             }
diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed b/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed
new file mode 100644 (file)
index 0000000..5ba7df8
--- /dev/null
@@ -0,0 +1,24 @@
+// run-rustfix
+
+// Test that we DO warn when lifetime name is not used at all.
+
+#![deny(unused_lifetimes)]
+#![allow(dead_code, unused_variables)]
+
+fn september() {}
+//~^ ERROR lifetime parameter `'a` never used
+//~| HELP remove it
+
+fn october<'b, T>(s: &'b T) -> &'b T {
+    //~^ ERROR lifetime parameter `'a` never used
+    //~| HELP remove it
+    s
+}
+
+fn november<'a>(s: &'a str) -> (&'a str) {
+    //~^ ERROR lifetime parameter `'b` never used
+    //~| HELP remove it
+    s
+}
+
+fn main() {}
index 7152d122f79a351b54c2a5df2972a095d37c49a1..a56d7fa8abc0275f40b323c8afc47bf2c948f6ae 100644 (file)
@@ -1,19 +1,24 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
+// run-rustfix
 
 // Test that we DO warn when lifetime name is not used at all.
 
 #![deny(unused_lifetimes)]
-#![allow(dead_code)]
-#![allow(unused_variables)]
+#![allow(dead_code, unused_variables)]
 
-fn d<'a>() { } //~ ERROR `'a` never used
+fn september<'a>() {}
+//~^ ERROR lifetime parameter `'a` never used
+//~| HELP remove it
 
-fn main() { }
+fn october<'a, 'b, T>(s: &'b T) -> &'b T {
+    //~^ ERROR lifetime parameter `'a` never used
+    //~| HELP remove it
+    s
+}
+
+fn november<'a, 'b>(s: &'a str) -> (&'a str) {
+    //~^ ERROR lifetime parameter `'b` never used
+    //~| HELP remove it
+    s
+}
+
+fn main() {}
index 322351a0a8e5b4485e1b691cbca7a27444d22d25..566c841cfa96984e853341f0fcc7c866b10e34d5 100644 (file)
@@ -1,14 +1,30 @@
 error: lifetime parameter `'a` never used
-  --> $DIR/zero-uses-in-fn.rs:17:6
+  --> $DIR/zero-uses-in-fn.rs:8:14
    |
-LL | fn d<'a>() { } //~ ERROR `'a` never used
-   |      ^^
+LL | fn september<'a>() {}
+   |             -^^- help: remove it
    |
 note: lint level defined here
-  --> $DIR/zero-uses-in-fn.rs:13:9
+  --> $DIR/zero-uses-in-fn.rs:5:9
    |
 LL | #![deny(unused_lifetimes)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: lifetime parameter `'a` never used
+  --> $DIR/zero-uses-in-fn.rs:12:12
+   |
+LL | fn october<'a, 'b, T>(s: &'b T) -> &'b T {
+   |            ^^--
+   |            |
+   |            help: remove it
+
+error: lifetime parameter `'b` never used
+  --> $DIR/zero-uses-in-fn.rs:18:17
+   |
+LL | fn november<'a, 'b>(s: &'a str) -> (&'a str) {
+   |               --^^
+   |               |
+   |               help: remove it
+
+error: aborting due to 3 previous errors
 
index a231c0bf003311ca348746f9481cda5ad78b9578..54803e1d2be4248dd652275b93f01b1d58addddb 100644 (file)
@@ -1,21 +1,10 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
 // Test that we DO warn when lifetime name is not used at all.
 
 #![deny(unused_lifetimes)]
-#![allow(dead_code)]
-#![allow(unused_variables)]
+#![allow(dead_code, unused_variables)]
 
-struct Foo { }
+struct Foo {}
 
-impl<'a> Foo { } //~ ERROR `'a` never used
+impl<'a> Foo {} //~ ERROR `'a` never used
 
-fn main() { }
+fn main() {}
index 34cb15c1339d8837c7b842fb95f58157b8a989b6..1b77ebdec99c6af0986e62cfea945893261dc773 100644 (file)
@@ -1,11 +1,11 @@
 error: lifetime parameter `'a` never used
-  --> $DIR/zero-uses-in-impl.rs:19:6
+  --> $DIR/zero-uses-in-impl.rs:8:6
    |
-LL | impl<'a> Foo { } //~ ERROR `'a` never used
-   |      ^^
+LL | impl<'a> Foo {} //~ ERROR `'a` never used
+   |     -^^- help: remove it
    |
 note: lint level defined here
-  --> $DIR/zero-uses-in-impl.rs:13:9
+  --> $DIR/zero-uses-in-impl.rs:3:9
    |
 LL | #![deny(unused_lifetimes)]
    |         ^^^^^^^^^^^^^^^^