about summary refs log tree commit diff
path: root/tests/ui/single-use-lifetime
diff options
context:
space:
mode:
authorAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-05 09:13:28 +0100
committerAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-11 09:32:08 +0000
commitcf2dff2b1e3fa55fa5415d524200070d0d7aacfe (patch)
tree40a88d9a46aaf3e8870676eb2538378b75a263eb /tests/ui/single-use-lifetime
parentca855e6e42787ecd062d81d53336fe6788ef51a9 (diff)
downloadrust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.tar.gz
rust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.zip
Move /src/test to /tests
Diffstat (limited to 'tests/ui/single-use-lifetime')
-rw-r--r--tests/ui/single-use-lifetime/derive-eq.rs11
-rw-r--r--tests/ui/single-use-lifetime/fn-types.rs16
-rw-r--r--tests/ui/single-use-lifetime/fn-types.stderr28
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-fn-argument.rs33
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-fn-argument.stderr59
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-fn-return.rs23
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs22
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr21
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs18
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr35
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-inherent-method-return.rs18
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr21
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-struct.rs28
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-trait-method-argument.rs26
-rw-r--r--tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr21
-rw-r--r--tests/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs15
-rw-r--r--tests/ui/single-use-lifetime/two-uses-in-fn-arguments.rs16
-rw-r--r--tests/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs17
-rw-r--r--tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.rs18
-rw-r--r--tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr21
-rw-r--r--tests/ui/single-use-lifetime/two-uses-in-trait-impl.rs22
-rw-r--r--tests/ui/single-use-lifetime/zero-uses-in-fn.fixed24
-rw-r--r--tests/ui/single-use-lifetime/zero-uses-in-fn.rs24
-rw-r--r--tests/ui/single-use-lifetime/zero-uses-in-fn.stderr30
-rw-r--r--tests/ui/single-use-lifetime/zero-uses-in-impl.rs10
-rw-r--r--tests/ui/single-use-lifetime/zero-uses-in-impl.stderr14
26 files changed, 591 insertions, 0 deletions
diff --git a/tests/ui/single-use-lifetime/derive-eq.rs b/tests/ui/single-use-lifetime/derive-eq.rs
new file mode 100644
index 00000000000..e5bdfc55dd6
--- /dev/null
+++ b/tests/ui/single-use-lifetime/derive-eq.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![deny(single_use_lifetimes)]
+
+#[derive(PartialEq, Eq)]
+struct Foo<'a, T> {
+    /// a reference to the underlying secret data that will be derefed
+    pub data: &'a mut T,
+}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/fn-types.rs b/tests/ui/single-use-lifetime/fn-types.rs
new file mode 100644
index 00000000000..018535f645d
--- /dev/null
+++ b/tests/ui/single-use-lifetime/fn-types.rs
@@ -0,0 +1,16 @@
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO warn when lifetime name is used only
+// once in a fn argument.
+
+struct Foo {
+  a: for<'a> fn(&'a u32), //~ ERROR `'a` only used once
+  b: for<'a> fn(&'a u32, &'a u32), // OK, used twice.
+  c: for<'a> fn(&'a u32) -> &'a u32, // OK, used twice.
+  d: for<'a> fn() -> &'a u32, // OK, used only in return type.
+    //~^ ERROR return type references lifetime `'a`, which is not constrained by the fn input types
+}
+
+fn main() { }
diff --git a/tests/ui/single-use-lifetime/fn-types.stderr b/tests/ui/single-use-lifetime/fn-types.stderr
new file mode 100644
index 00000000000..55959def4f3
--- /dev/null
+++ b/tests/ui/single-use-lifetime/fn-types.stderr
@@ -0,0 +1,28 @@
+error: lifetime parameter `'a` only used once
+  --> $DIR/fn-types.rs:9:10
+   |
+LL |   a: for<'a> fn(&'a u32),
+   |          ^^      -- ...is used only here
+   |          |
+   |          this lifetime...
+   |
+note: the lint level is defined here
+  --> $DIR/fn-types.rs:1:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL -   a: for<'a> fn(&'a u32),
+LL +   a: fn(&u32),
+   |
+
+error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
+  --> $DIR/fn-types.rs:12:22
+   |
+LL |   d: for<'a> fn() -> &'a u32, // OK, used only in return type.
+   |                      ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0581`.
diff --git a/tests/ui/single-use-lifetime/one-use-in-fn-argument.rs b/tests/ui/single-use-lifetime/one-use-in-fn-argument.rs
new file mode 100644
index 00000000000..7919ef820f6
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-fn-argument.rs
@@ -0,0 +1,33 @@
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO warn when lifetime name is used only
+// once in a fn argument.
+
+fn a<'a>(x: &'a u32) { //~ ERROR `'a` only used once
+    //~^ HELP elide the single-use lifetime
+}
+
+struct Single<'a> { x: &'a u32 }
+struct Double<'a, 'b> { f: &'a &'b u32 }
+
+fn center<'m>(_: Single<'m>) {} //~ ERROR `'m` only used once
+//~^ HELP elide the single-use lifetime
+fn left<'x, 'y>(foo: Double<'x, 'y>) -> &'x u32 { foo.f } //~ ERROR `'y` only used once
+//~^ HELP elide the single-use lifetime
+fn right<'x, 'y>(foo: Double<'x, 'y>) -> &'y u32 { foo.f } //~ ERROR `'x` only used once
+//~^ HELP elide the single-use lifetime
+
+pub trait Tfv<'a> {}
+
+// Do NOT lint in an HRTB.
+pub fn g<T: for<'a> Tfv<'a>>() {}
+
+// Do NOT lint for trait bounds.
+pub fn h<'a, S>(_: S)
+where
+    S: Tfv<'a>,
+{}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/one-use-in-fn-argument.stderr b/tests/ui/single-use-lifetime/one-use-in-fn-argument.stderr
new file mode 100644
index 00000000000..93f16f5bad5
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-fn-argument.stderr
@@ -0,0 +1,59 @@
+error: lifetime parameter `'a` only used once
+  --> $DIR/one-use-in-fn-argument.rs:8:6
+   |
+LL | fn a<'a>(x: &'a u32) {
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
+   |
+note: the lint level is defined here
+  --> $DIR/one-use-in-fn-argument.rs:1:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL - fn a<'a>(x: &'a u32) {
+LL + fn a(x: &u32) {
+   |
+
+error: lifetime parameter `'m` only used once
+  --> $DIR/one-use-in-fn-argument.rs:15:11
+   |
+LL | fn center<'m>(_: Single<'m>) {}
+   |           ^^            -- ...is used only here
+   |           |
+   |           this lifetime...
+   |
+help: elide the single-use lifetime
+   |
+LL - fn center<'m>(_: Single<'m>) {}
+LL + fn center(_: Single<'_>) {}
+   |
+
+error: lifetime parameter `'y` only used once
+  --> $DIR/one-use-in-fn-argument.rs:17:13
+   |
+LL | fn left<'x, 'y>(foo: Double<'x, 'y>) -> &'x u32 { foo.f }
+   |             ^^ this lifetime... -- ...is used only here
+   |
+help: elide the single-use lifetime
+   |
+LL - fn left<'x, 'y>(foo: Double<'x, 'y>) -> &'x u32 { foo.f }
+LL + fn left<'x>(foo: Double<'x, '_>) -> &'x u32 { foo.f }
+   |
+
+error: lifetime parameter `'x` only used once
+  --> $DIR/one-use-in-fn-argument.rs:19:10
+   |
+LL | fn right<'x, 'y>(foo: Double<'x, 'y>) -> &'y u32 { foo.f }
+   |          ^^ this lifetime... -- ...is used only here
+   |
+help: elide the single-use lifetime
+   |
+LL - fn right<'x, 'y>(foo: Double<'x, 'y>) -> &'y u32 { foo.f }
+LL + fn right<'y>(foo: Double<'_, 'y>) -> &'y u32 { foo.f }
+   |
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/single-use-lifetime/one-use-in-fn-return.rs b/tests/ui/single-use-lifetime/one-use-in-fn-return.rs
new file mode 100644
index 00000000000..1ade01eed36
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-fn-return.rs
@@ -0,0 +1,23 @@
+// Test that we DO NOT warn when lifetime name is used only
+// once in a fn return type -- using `'_` is not legal there,
+// as it must refer back to an argument.
+//
+// (Normally, using `'static` would be preferred, but there are
+// times when that is not what you want.)
+
+// check-pass
+
+#![deny(single_use_lifetimes)]
+
+// OK: used only in return type
+fn b<'a>() -> &'a u32 {
+    &22
+}
+
+pub trait Tfv<'a> {}
+impl Tfv<'_> for () {}
+
+// Do NOT lint if used in return type.
+pub fn i<'a>() -> impl Tfv<'a> {}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs b/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs
new file mode 100644
index 00000000000..64f1c9118a1
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs
@@ -0,0 +1,22 @@
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO warn for a lifetime used only once in an impl, and that we
+// don't warn for the anonymous lifetime.
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Foo<'f> { //~ ERROR `'f` only used once
+    fn inherent_a(&self) {
+    }
+}
+
+impl Foo<'_> {
+    fn inherent_b(&self) {}
+}
+
+
+fn main() { }
diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr b/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr
new file mode 100644
index 00000000000..94129560f40
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr
@@ -0,0 +1,21 @@
+error: lifetime parameter `'f` only used once
+  --> $DIR/one-use-in-inherent-impl-header.rs:12:6
+   |
+LL | impl<'f> Foo<'f> {
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
+   |
+note: the lint level is defined here
+  --> $DIR/one-use-in-inherent-impl-header.rs:1:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL - impl<'f> Foo<'f> {
+LL + impl Foo<'_> {
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs b/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs
new file mode 100644
index 00000000000..eecd715efc1
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs
@@ -0,0 +1,18 @@
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO warn for a lifetime used only once in an inherent method.
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Foo<'f> { //~ ERROR `'f` only used once
+    //~^ HELP elide the single-use lifetime
+    fn inherent_a<'a>(&self, data: &'a u32) { //~ ERROR `'a` only used once
+        //~^ HELP elide the single-use lifetime
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr b/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr
new file mode 100644
index 00000000000..39507785bbe
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr
@@ -0,0 +1,35 @@
+error: lifetime parameter `'f` only used once
+  --> $DIR/one-use-in-inherent-method-argument.rs:11:6
+   |
+LL | impl<'f> Foo<'f> {
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
+   |
+note: the lint level is defined here
+  --> $DIR/one-use-in-inherent-method-argument.rs:1:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL - impl<'f> Foo<'f> {
+LL + impl Foo<'_> {
+   |
+
+error: lifetime parameter `'a` only used once
+  --> $DIR/one-use-in-inherent-method-argument.rs:13:19
+   |
+LL |     fn inherent_a<'a>(&self, data: &'a u32) {
+   |                   ^^                -- ...is used only here
+   |                   |
+   |                   this lifetime...
+   |
+help: elide the single-use lifetime
+   |
+LL -     fn inherent_a<'a>(&self, data: &'a u32) {
+LL +     fn inherent_a(&self, data: &u32) {
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.rs b/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.rs
new file mode 100644
index 00000000000..c5938f4a10b
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.rs
@@ -0,0 +1,18 @@
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO NOT warn for a lifetime used just once in a return type,
+// where that return type is in an inherent method.
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Foo<'f> { //~ ERROR `'f` only used once
+    fn inherent_a<'a>(&self) -> &'a u32 { // OK for 'a
+        &22
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr b/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr
new file mode 100644
index 00000000000..69578fe2f88
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr
@@ -0,0 +1,21 @@
+error: lifetime parameter `'f` only used once
+  --> $DIR/one-use-in-inherent-method-return.rs:12:6
+   |
+LL | impl<'f> Foo<'f> {
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
+   |
+note: the lint level is defined here
+  --> $DIR/one-use-in-inherent-method-return.rs:1:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL - impl<'f> Foo<'f> {
+LL + impl Foo<'_> {
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/single-use-lifetime/one-use-in-struct.rs b/tests/ui/single-use-lifetime/one-use-in-struct.rs
new file mode 100644
index 00000000000..9cad942e7a2
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-struct.rs
@@ -0,0 +1,28 @@
+// Test that we do not warn for named lifetimes in structs,
+// even when they are only used once (since to not use a named
+// lifetime is illegal!)
+//
+// check-pass
+
+// Use forbid to verify that `automatically_derived` is handled correctly.
+#![forbid(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Foo<'f> {
+    data: &'f u32,
+}
+
+enum Bar<'f> {
+    Data(&'f u32),
+}
+
+trait Baz<'f> {}
+
+// `Derive`d impls shouldn't trigger a warning, either (Issue #53738).
+#[derive(Debug)]
+struct Quux<'a> {
+    priors: &'a u32,
+}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.rs b/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.rs
new file mode 100644
index 00000000000..1848fc91c62
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.rs
@@ -0,0 +1,26 @@
+// Test that we DO warn for a lifetime on an impl used only in `&self`
+// in a trait method.
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Iterator for Foo<'f> {
+    type Item = &'f u32;
+
+    fn next<'g>(&'g mut self) -> Option<Self::Item> { //~ ERROR `'g` only used once
+        //~^ HELP elide the single-use lifetime
+        None
+    }
+}
+
+trait Bar<'a> {
+    // But we should not warn here.
+    fn bar(x: Foo<'a>);
+}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr b/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr
new file mode 100644
index 00000000000..1a6e8310d30
--- /dev/null
+++ b/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr
@@ -0,0 +1,21 @@
+error: lifetime parameter `'g` only used once
+  --> $DIR/one-use-in-trait-method-argument.rs:15:13
+   |
+LL |     fn next<'g>(&'g mut self) -> Option<Self::Item> {
+   |             ^^   -- ...is used only here
+   |             |
+   |             this lifetime...
+   |
+note: the lint level is defined here
+  --> $DIR/one-use-in-trait-method-argument.rs:4:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL -     fn next<'g>(&'g mut self) -> Option<Self::Item> {
+LL +     fn next(&mut self) -> Option<Self::Item> {
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs b/tests/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs
new file mode 100644
index 00000000000..f80f3f63c66
--- /dev/null
+++ b/tests/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs
@@ -0,0 +1,15 @@
+// Test that we DO NOT warn when lifetime name is used in
+// both the argument and return.
+//
+// check-pass
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// OK: used twice
+fn c<'a>(x: &'a u32) -> &'a u32 {
+    &22
+}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/two-uses-in-fn-arguments.rs b/tests/ui/single-use-lifetime/two-uses-in-fn-arguments.rs
new file mode 100644
index 00000000000..51724ebf898
--- /dev/null
+++ b/tests/ui/single-use-lifetime/two-uses-in-fn-arguments.rs
@@ -0,0 +1,16 @@
+// Test that we DO NOT warn when lifetime name is used multiple
+// arguments, or more than once in a single argument.
+//
+// check-pass
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// OK: used twice
+fn c<'a>(x: &'a u32, y: &'a u32) {}
+
+// OK: used twice
+fn d<'a>(x: (&'a u32, &'a u32)) {}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs b/tests/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs
new file mode 100644
index 00000000000..125a395db3b
--- /dev/null
+++ b/tests/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs
@@ -0,0 +1,17 @@
+// Test that we DO NOT warn for a lifetime used twice in an impl.
+//
+// check-pass
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Foo<'f> {
+    data: &'f u32,
+}
+
+impl<'f> Foo<'f> {
+    fn inherent_a(&self, data: &'f u32) {}
+}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.rs b/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.rs
new file mode 100644
index 00000000000..06ab6cdbfae
--- /dev/null
+++ b/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.rs
@@ -0,0 +1,18 @@
+// Test that we DO NOT warn for a lifetime used twice in an impl method and
+// header.
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Foo<'f> { //~ ERROR `'f` only used once
+    fn inherent_a<'a>(&self, data: &'a u32) -> &'a u32{
+      data
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr b/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr
new file mode 100644
index 00000000000..4794566eae4
--- /dev/null
+++ b/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr
@@ -0,0 +1,21 @@
+error: lifetime parameter `'f` only used once
+  --> $DIR/two-uses-in-inherent-method-argument-and-return.rs:12:6
+   |
+LL | impl<'f> Foo<'f> {
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
+   |
+note: the lint level is defined here
+  --> $DIR/two-uses-in-inherent-method-argument-and-return.rs:4:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL - impl<'f> Foo<'f> {
+LL + impl Foo<'_> {
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/single-use-lifetime/two-uses-in-trait-impl.rs b/tests/ui/single-use-lifetime/two-uses-in-trait-impl.rs
new file mode 100644
index 00000000000..16431a39fd0
--- /dev/null
+++ b/tests/ui/single-use-lifetime/two-uses-in-trait-impl.rs
@@ -0,0 +1,22 @@
+// Test that we DO NOT warn for a lifetime on an impl used in both
+// header and in an associated type.
+//
+// check-pass
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Foo<'f> {
+    data: &'f u32,
+}
+
+impl<'f> Iterator for Foo<'f> {
+    type Item = &'f u32;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        None
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/zero-uses-in-fn.fixed b/tests/ui/single-use-lifetime/zero-uses-in-fn.fixed
new file mode 100644
index 00000000000..0f26a975a37
--- /dev/null
+++ b/tests/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 elide the unused lifetime
+
+fn october<'b, T>(s: &'b T) -> &'b T {
+    //~^ ERROR lifetime parameter `'a` never used
+    //~| HELP elide the unused lifetime
+    s
+}
+
+fn november<'a>(s: &'a str) -> &'a str {
+    //~^ ERROR lifetime parameter `'b` never used
+    //~| HELP elide the unused lifetime
+    s
+}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/zero-uses-in-fn.rs b/tests/ui/single-use-lifetime/zero-uses-in-fn.rs
new file mode 100644
index 00000000000..7f9504fe5a9
--- /dev/null
+++ b/tests/ui/single-use-lifetime/zero-uses-in-fn.rs
@@ -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<'a>() {}
+//~^ ERROR lifetime parameter `'a` never used
+//~| HELP elide the unused lifetime
+
+fn october<'a, 'b, T>(s: &'b T) -> &'b T {
+    //~^ ERROR lifetime parameter `'a` never used
+    //~| HELP elide the unused lifetime
+    s
+}
+
+fn november<'a, 'b>(s: &'a str) -> &'a str {
+    //~^ ERROR lifetime parameter `'b` never used
+    //~| HELP elide the unused lifetime
+    s
+}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/zero-uses-in-fn.stderr b/tests/ui/single-use-lifetime/zero-uses-in-fn.stderr
new file mode 100644
index 00000000000..59c0164e324
--- /dev/null
+++ b/tests/ui/single-use-lifetime/zero-uses-in-fn.stderr
@@ -0,0 +1,30 @@
+error: lifetime parameter `'a` never used
+  --> $DIR/zero-uses-in-fn.rs:8:14
+   |
+LL | fn september<'a>() {}
+   |             -^^- help: elide the unused lifetime
+   |
+note: the lint level is defined here
+  --> $DIR/zero-uses-in-fn.rs:5:9
+   |
+LL | #![deny(unused_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^
+
+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: elide the unused lifetime
+
+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: elide the unused lifetime
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/single-use-lifetime/zero-uses-in-impl.rs b/tests/ui/single-use-lifetime/zero-uses-in-impl.rs
new file mode 100644
index 00000000000..54803e1d2be
--- /dev/null
+++ b/tests/ui/single-use-lifetime/zero-uses-in-impl.rs
@@ -0,0 +1,10 @@
+// Test that we DO warn when lifetime name is not used at all.
+
+#![deny(unused_lifetimes)]
+#![allow(dead_code, unused_variables)]
+
+struct Foo {}
+
+impl<'a> Foo {} //~ ERROR `'a` never used
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/zero-uses-in-impl.stderr b/tests/ui/single-use-lifetime/zero-uses-in-impl.stderr
new file mode 100644
index 00000000000..b6e42d3e717
--- /dev/null
+++ b/tests/ui/single-use-lifetime/zero-uses-in-impl.stderr
@@ -0,0 +1,14 @@
+error: lifetime parameter `'a` never used
+  --> $DIR/zero-uses-in-impl.rs:8:6
+   |
+LL | impl<'a> Foo {}
+   |     -^^- help: elide the unused lifetime
+   |
+note: the lint level is defined here
+  --> $DIR/zero-uses-in-impl.rs:3:9
+   |
+LL | #![deny(unused_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+