about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/resolve_lifetime.rs46
-rw-r--r--src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed24
-rw-r--r--src/test/ui/single-use-lifetime/zero-uses-in-fn.rs31
-rw-r--r--src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr26
-rw-r--r--src/test/ui/single-use-lifetime/zero-uses-in-impl.rs19
-rw-r--r--src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr8
6 files changed, 113 insertions, 41 deletions
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index a10b387672a..2f3fdb7966f 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -19,9 +19,9 @@ use hir::def::Def;
 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;
@@ -1398,6 +1398,30 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults;
     }
 
+    /// helper method to determine the span to remove when suggesting the
+    /// deletion of a lifetime
+    fn lifetime_deletion_span(&self, name: ast::Ident, generics: &hir::Generics) -> Option<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
+                    }
+                })
+        }
+    }
+
     fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
         let defined_by = match self.scope {
             Scope::Binder { lifetimes, .. } => lifetimes,
@@ -1468,12 +1492,26 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                         _ => 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(generics) = self.tcx.hir.get_generics(parent_def_id) {
+                                let unused_lt_span = self.lifetime_deletion_span(name, generics);
+                                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
index 00000000000..5ba7df8a1e6
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed
@@ -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() {}
diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs b/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs
index 7152d122f79..a56d7fa8abc 100644
--- a/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs
+++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs
@@ -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() {}
diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr b/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr
index 322351a0a8e..566c841cfa9 100644
--- a/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr
+++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr
@@ -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
 
diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-impl.rs b/src/test/ui/single-use-lifetime/zero-uses-in-impl.rs
index a231c0bf003..54803e1d2be 100644
--- a/src/test/ui/single-use-lifetime/zero-uses-in-impl.rs
+++ b/src/test/ui/single-use-lifetime/zero-uses-in-impl.rs
@@ -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() {}
diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr b/src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr
index 34cb15c1339..1b77ebdec99 100644
--- a/src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr
+++ b/src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr
@@ -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)]
    |         ^^^^^^^^^^^^^^^^