about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-05-07 19:35:25 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-05-17 20:31:13 +0000
commitd1d585d039ace2ea72db8772166773a80a661905 (patch)
tree88ce9952605e7c791bd2a1c9edb671fb06867d6d
parent120049fab4e293c19fa1c5a09d68f89bcd940b36 (diff)
downloadrust-d1d585d039ace2ea72db8772166773a80a661905.tar.gz
rust-d1d585d039ace2ea72db8772166773a80a661905.zip
Account for owning item lifetimes in suggestion and annotate tests as `run-rustfix`
```
error: lifetime may not live long enough
  --> $DIR/lt-ref-self.rs:12:9
   |
LL |     fn ref_self(&self, f: &u32) -> &u32 {
   |                 -         - let's call the lifetime of this reference `'1`
   |                 |
   |                 let's call the lifetime of this reference `'2`
LL |         f
   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
   |
help: consider introducing a named lifetime parameter and update trait if needed
   |
LL |     fn ref_self<'b>(&'b self, f: &'b u32) -> &'b u32 {
   |                ++++  ++           ++          ++
```
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs42
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.fixed17
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs6
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr2
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.fixed14
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs4
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr2
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs3
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr4
-rw-r--r--tests/ui/self/elision/lt-ref-self-async.fixed45
-rw-r--r--tests/ui/self/elision/lt-ref-self-async.rs4
-rw-r--r--tests/ui/self/elision/lt-ref-self-async.stderr12
-rw-r--r--tests/ui/self/elision/lt-ref-self.fixed44
-rw-r--r--tests/ui/self/elision/lt-ref-self.rs3
-rw-r--r--tests/ui/self/elision/lt-ref-self.stderr24
-rw-r--r--tests/ui/self/elision/ref-mut-self.fixed44
-rw-r--r--tests/ui/self/elision/ref-mut-self.rs3
-rw-r--r--tests/ui/self/elision/ref-mut-self.stderr12
-rw-r--r--tests/ui/self/elision/ref-mut-struct.fixed37
-rw-r--r--tests/ui/self/elision/ref-mut-struct.rs3
-rw-r--r--tests/ui/self/elision/ref-mut-struct.stderr10
-rw-r--r--tests/ui/self/elision/ref-self.fixed59
-rw-r--r--tests/ui/self/elision/ref-self.rs5
-rw-r--r--tests/ui/self/elision/ref-self.stderr14
-rw-r--r--tests/ui/self/elision/ref-struct.fixed37
-rw-r--r--tests/ui/self/elision/ref-struct.rs3
-rw-r--r--tests/ui/self/elision/ref-struct.stderr10
27 files changed, 404 insertions, 59 deletions
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 4db79af10a5..f60ecb3f453 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1,4 +1,5 @@
 use hir::GenericParamKind;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{
     codes::*, Applicability, Diag, DiagMessage, DiagStyledString, EmissionGuarantee, IntoDiagArg,
     MultiSpan, SubdiagMessageOp, Subdiagnostic,
@@ -362,13 +363,27 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
 
             let node = self.tcx.hir_node_by_def_id(anon_reg.def_id);
             let is_impl = matches!(&node, hir::Node::ImplItem(_));
-            let generics = match node {
+            let (generics, parent_generics) = match node {
                 hir::Node::Item(&hir::Item {
                     kind: hir::ItemKind::Fn(_, ref generics, ..),
                     ..
                 })
                 | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
-                | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => generics,
+                | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => (
+                    generics,
+                    match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.def_id))
+                    {
+                        hir::Node::Item(hir::Item {
+                            kind: hir::ItemKind::Trait(_, _, ref generics, ..),
+                            ..
+                        })
+                        | hir::Node::Item(hir::Item {
+                            kind: hir::ItemKind::Impl(hir::Impl { ref generics, .. }),
+                            ..
+                        }) => Some(generics),
+                        _ => None,
+                    },
+                ),
                 _ => return false,
             };
 
@@ -379,8 +394,29 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
                 .map(|p| p.name.ident().name)
                 .find(|i| *i != kw::UnderscoreLifetime);
             let introduce_new = suggestion_param_name.is_none();
+
+            let mut default = "'a".to_string();
+            if let Some(parent_generics) = parent_generics {
+                let used: FxHashSet<_> = parent_generics
+                    .params
+                    .iter()
+                    .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
+                    .map(|p| p.name.ident().name)
+                    .filter(|i| *i != kw::UnderscoreLifetime)
+                    .map(|l| l.to_string())
+                    .collect();
+                if let Some(lt) =
+                    ('a'..='z').map(|it| format!("'{it}")).find(|it| !used.contains(it))
+                {
+                    // We want a lifetime that *isn't* present in the `trait` or `impl` that assoc
+                    // `fn` belongs to. We could suggest reusing one of their lifetimes, but it is
+                    // likely to be an over-constraining lifetime requirement, so we always add a
+                    // lifetime to the `fn`.
+                    default = lt;
+                }
+            }
             let suggestion_param_name =
-                suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| "'a".to_owned());
+                suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| default);
 
             struct ImplicitLifetimeFinder {
                 suggestions: Vec<(Span, String)>,
diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.fixed b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.fixed
new file mode 100644
index 00000000000..b5513818f63
--- /dev/null
+++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.fixed
@@ -0,0 +1,17 @@
+//@ run-rustfix
+#![allow(dead_code)]
+struct Foo {
+    field: i32,
+}
+
+impl Foo {
+  fn foo<'a>(&'a self, x: &'a i32) -> &'a i32 {
+
+    x
+    //~^ ERROR lifetime may not live long enough
+
+  }
+
+}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs
index 49993aca3ca..52646ff89eb 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs
+++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs
@@ -1,5 +1,7 @@
+//@ run-rustfix
+#![allow(dead_code)]
 struct Foo {
-  field: i32
+    field: i32,
 }
 
 impl Foo {
@@ -12,4 +14,4 @@ impl Foo {
 
 }
 
-fn main() { }
+fn main() {}
diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
index 5cfa5717224..e2f42cbfb28 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:8:5
+  --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:10:5
    |
 LL |   fn foo<'a>(&self, x: &'a i32) -> &i32 {
    |          --  - let's call the lifetime of this reference `'1`
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.fixed b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.fixed
new file mode 100644
index 00000000000..d9f454f346c
--- /dev/null
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.fixed
@@ -0,0 +1,14 @@
+//@ run-rustfix
+#![allow(dead_code)]
+struct Foo {
+  field: i32,
+}
+
+impl Foo {
+  fn foo<'a>(&'a self, x: &'a i32) -> &'a i32 {
+    x
+    //~^ ERROR lifetime may not live long enough
+  }
+}
+
+fn main() { }
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs
index 3ffd7be4e73..bf66a551a80 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs
@@ -1,5 +1,7 @@
+//@ run-rustfix
+#![allow(dead_code)]
 struct Foo {
-  field: i32
+  field: i32,
 }
 
 impl Foo {
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
index fd15d516999..778634e95be 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:7:5
+  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:9:5
    |
 LL |   fn foo<'a>(&self, x: &i32) -> &i32 {
    |              -         - let's call the lifetime of this reference `'1`
diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
index f1a3fb0185d..3b2c8c7bc79 100644
--- a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
+++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
@@ -6,6 +6,9 @@ impl Foo {
     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
     //~^ lifetime may not live long enough
 
+    // For this suggestion to be right, we'd need to also suggest `self: Pin<&'a Self>`, which we
+    // don't, but we provide a follow up suggestion to do so, so I condider that good at least for
+    // now.
     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
     //~^ lifetime may not live long enough
 }
diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
index 3e2bbd37f33..773f9362ec5 100644
--- a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
+++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
@@ -13,7 +13,7 @@ LL |     fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &'a Foo { f }
    |         ++++            ++           ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:9:69
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:12:69
    |
 LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
    |                    -          -                                     ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
@@ -27,7 +27,7 @@ LL |     fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&'a Foo>, &'
    |         ++++            ++            ++                        ++        ++
 
 error: lifetime may not live long enough
-  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:15:58
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:18:58
    |
 LL |     fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
    |            --  ---- has type `Pin<&'1 Foo>`              ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
diff --git a/tests/ui/self/elision/lt-ref-self-async.fixed b/tests/ui/self/elision/lt-ref-self-async.fixed
new file mode 100644
index 00000000000..6d875ef0cec
--- /dev/null
+++ b/tests/ui/self/elision/lt-ref-self-async.fixed
@@ -0,0 +1,45 @@
+//@ edition:2018
+//@ run-rustfix
+#![allow(non_snake_case, dead_code)]
+
+use std::pin::Pin;
+
+struct Struct<'a> { data: &'a u32 }
+
+impl<'a> Struct<'a> {
+    // Test using `&self` sugar:
+
+    async fn ref_self<'b>(&'b self, f: &'b u32) -> &u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    // Test using `&Self` explicitly:
+
+    async fn ref_Self<'b>(self: &'b Self, f: &'b u32) -> &u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    async fn box_ref_Self<'b>(self: Box<&'b Self>, f: &'b u32) -> &u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    async fn pin_ref_Self<'b>(self: Pin<&'b Self>, f: &'b u32) -> &u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    async fn box_box_ref_Self<'b>(self: Box<Box<&'b Self>>, f: &'b u32) -> &u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    async fn box_pin_Self<'b>(self: Box<Pin<&'b Self>>, f: &'b u32) -> &u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/self/elision/lt-ref-self-async.rs b/tests/ui/self/elision/lt-ref-self-async.rs
index 8eb4a48a9c9..a70e22ab77a 100644
--- a/tests/ui/self/elision/lt-ref-self-async.rs
+++ b/tests/ui/self/elision/lt-ref-self-async.rs
@@ -1,6 +1,6 @@
 //@ edition:2018
-
-#![allow(non_snake_case)]
+//@ run-rustfix
+#![allow(non_snake_case, dead_code)]
 
 use std::pin::Pin;
 
diff --git a/tests/ui/self/elision/lt-ref-self-async.stderr b/tests/ui/self/elision/lt-ref-self-async.stderr
index 29d60ed6635..c8b49de7671 100644
--- a/tests/ui/self/elision/lt-ref-self-async.stderr
+++ b/tests/ui/self/elision/lt-ref-self-async.stderr
@@ -10,7 +10,7 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     async fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+LL |     async fn ref_self<'b>(&'b self, f: &'b u32) -> &u32 {
    |                      ++++  ++           ++
 
 error: lifetime may not live long enough
@@ -25,7 +25,7 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     async fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+LL |     async fn ref_Self<'b>(self: &'b Self, f: &'b u32) -> &u32 {
    |                      ++++        ++           ++
 
 error: lifetime may not live long enough
@@ -40,7 +40,7 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     async fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+LL |     async fn box_ref_Self<'b>(self: Box<&'b Self>, f: &'b u32) -> &u32 {
    |                          ++++            ++            ++
 
 error: lifetime may not live long enough
@@ -55,7 +55,7 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     async fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+LL |     async fn pin_ref_Self<'b>(self: Pin<&'b Self>, f: &'b u32) -> &u32 {
    |                          ++++            ++            ++
 
 error: lifetime may not live long enough
@@ -70,7 +70,7 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     async fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+LL |     async fn box_box_ref_Self<'b>(self: Box<Box<&'b Self>>, f: &'b u32) -> &u32 {
    |                              ++++                ++             ++
 
 error: lifetime may not live long enough
@@ -85,7 +85,7 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     async fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+LL |     async fn box_pin_Self<'b>(self: Box<Pin<&'b Self>>, f: &'b u32) -> &u32 {
    |                          ++++                ++             ++
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/self/elision/lt-ref-self.fixed b/tests/ui/self/elision/lt-ref-self.fixed
new file mode 100644
index 00000000000..c9faa86c441
--- /dev/null
+++ b/tests/ui/self/elision/lt-ref-self.fixed
@@ -0,0 +1,44 @@
+//@ run-rustfix
+#![allow(non_snake_case, dead_code)]
+
+use std::pin::Pin;
+
+struct Struct<'a> { data: &'a u32 }
+
+impl<'a> Struct<'a> {
+    // Test using `&self` sugar:
+
+    fn ref_self<'b>(&'b self, f: &'b u32) -> &'b u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    // Test using `&Self` explicitly:
+
+    fn ref_Self<'b>(self: &'b Self, f: &'b u32) -> &'b u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_ref_Self<'b>(self: Box<&'b Self>, f: &'b u32) -> &'b u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn pin_ref_Self<'b>(self: Pin<&'b Self>, f: &'b u32) -> &'b u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_box_ref_Self<'b>(self: Box<Box<&'b Self>>, f: &'b u32) -> &'b u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_pin_Self<'b>(self: Box<Pin<&'b Self>>, f: &'b u32) -> &'b u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/self/elision/lt-ref-self.rs b/tests/ui/self/elision/lt-ref-self.rs
index d37ed5acbcb..fbd0665b22d 100644
--- a/tests/ui/self/elision/lt-ref-self.rs
+++ b/tests/ui/self/elision/lt-ref-self.rs
@@ -1,4 +1,5 @@
-#![allow(non_snake_case)]
+//@ run-rustfix
+#![allow(non_snake_case, dead_code)]
 
 use std::pin::Pin;
 
diff --git a/tests/ui/self/elision/lt-ref-self.stderr b/tests/ui/self/elision/lt-ref-self.stderr
index 5eaaa7698b6..53b662bcb69 100644
--- a/tests/ui/self/elision/lt-ref-self.stderr
+++ b/tests/ui/self/elision/lt-ref-self.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:11:9
+  --> $DIR/lt-ref-self.rs:12:9
    |
 LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                 -         - let's call the lifetime of this reference `'1`
@@ -10,11 +10,11 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     fn ref_self<'a>(&'a self, f: &'a u32) -> &'a u32 {
+LL |     fn ref_self<'b>(&'b self, f: &'b u32) -> &'b u32 {
    |                ++++  ++           ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:18:9
+  --> $DIR/lt-ref-self.rs:19:9
    |
 LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                       -         - let's call the lifetime of this reference `'1`
@@ -25,11 +25,11 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &'a u32 {
+LL |     fn ref_Self<'b>(self: &'b Self, f: &'b u32) -> &'b u32 {
    |                ++++        ++           ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:23:9
+  --> $DIR/lt-ref-self.rs:24:9
    |
 LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                               -          - let's call the lifetime of this reference `'1`
@@ -40,11 +40,11 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &'a u32 {
+LL |     fn box_ref_Self<'b>(self: Box<&'b Self>, f: &'b u32) -> &'b u32 {
    |                    ++++            ++            ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:28:9
+  --> $DIR/lt-ref-self.rs:29:9
    |
 LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                               -          - let's call the lifetime of this reference `'1`
@@ -55,11 +55,11 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &'a u32 {
+LL |     fn pin_ref_Self<'b>(self: Pin<&'b Self>, f: &'b u32) -> &'b u32 {
    |                    ++++            ++            ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:33:9
+  --> $DIR/lt-ref-self.rs:34:9
    |
 LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                       -           - let's call the lifetime of this reference `'1`
@@ -70,11 +70,11 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &'a u32 {
+LL |     fn box_box_ref_Self<'b>(self: Box<Box<&'b Self>>, f: &'b u32) -> &'b u32 {
    |                        ++++                ++             ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/lt-ref-self.rs:38:9
+  --> $DIR/lt-ref-self.rs:39:9
    |
 LL |     fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                   -           - let's call the lifetime of this reference `'1`
@@ -85,7 +85,7 @@ LL |         f
    |
 help: consider introducing a named lifetime parameter and update trait if needed
    |
-LL |     fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &'a u32 {
+LL |     fn box_pin_Self<'b>(self: Box<Pin<&'b Self>>, f: &'b u32) -> &'b u32 {
    |                    ++++                ++             ++          ++
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/self/elision/ref-mut-self.fixed b/tests/ui/self/elision/ref-mut-self.fixed
new file mode 100644
index 00000000000..90e50221a19
--- /dev/null
+++ b/tests/ui/self/elision/ref-mut-self.fixed
@@ -0,0 +1,44 @@
+//@ run-rustfix
+#![allow(non_snake_case, dead_code)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+impl Struct {
+    // Test using `&mut self` sugar:
+
+    fn ref_self<'a>(&'a mut self, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    // Test using `&mut Self` explicitly:
+
+    fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/self/elision/ref-mut-self.rs b/tests/ui/self/elision/ref-mut-self.rs
index bb82e6be748..a09fcdfcbb2 100644
--- a/tests/ui/self/elision/ref-mut-self.rs
+++ b/tests/ui/self/elision/ref-mut-self.rs
@@ -1,4 +1,5 @@
-#![allow(non_snake_case)]
+//@ run-rustfix
+#![allow(non_snake_case, dead_code)]
 
 use std::pin::Pin;
 
diff --git a/tests/ui/self/elision/ref-mut-self.stderr b/tests/ui/self/elision/ref-mut-self.stderr
index 8fea05e493d..a09034e5f71 100644
--- a/tests/ui/self/elision/ref-mut-self.stderr
+++ b/tests/ui/self/elision/ref-mut-self.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:11:9
+  --> $DIR/ref-mut-self.rs:12:9
    |
 LL |     fn ref_self(&mut self, f: &u32) -> &u32 {
    |                 -             - let's call the lifetime of this reference `'1`
@@ -14,7 +14,7 @@ LL |     fn ref_self<'a>(&'a mut self, f: &'a u32) -> &'a u32 {
    |                ++++  ++               ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:18:9
+  --> $DIR/ref-mut-self.rs:19:9
    |
 LL |     fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
    |                       -             - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |     fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &'a u32 {
    |                ++++        ++               ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:23:9
+  --> $DIR/ref-mut-self.rs:24:9
    |
 LL |     fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
    |                               -              - let's call the lifetime of this reference `'1`
@@ -44,7 +44,7 @@ LL |     fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &'a u32 {
    |                    ++++            ++                ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:28:9
+  --> $DIR/ref-mut-self.rs:29:9
    |
 LL |     fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
    |                               -              - let's call the lifetime of this reference `'1`
@@ -59,7 +59,7 @@ LL |     fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &'a u32 {
    |                    ++++            ++                ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:33:9
+  --> $DIR/ref-mut-self.rs:34:9
    |
 LL |     fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
    |                                       -               - let's call the lifetime of this reference `'1`
@@ -74,7 +74,7 @@ LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &'
    |                        ++++                ++                 ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-self.rs:38:9
+  --> $DIR/ref-mut-self.rs:39:9
    |
 LL |     fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
    |                                       -               - let's call the lifetime of this reference `'1`
diff --git a/tests/ui/self/elision/ref-mut-struct.fixed b/tests/ui/self/elision/ref-mut-struct.fixed
new file mode 100644
index 00000000000..275fafbad53
--- /dev/null
+++ b/tests/ui/self/elision/ref-mut-struct.fixed
@@ -0,0 +1,37 @@
+//@ run-rustfix
+#![allow(non_snake_case, dead_code)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+impl Struct {
+    // Test using `&mut Struct` explicitly:
+
+    fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_pin_ref_Struct<'a>(self: Box<Pin<&'a mut Struct>>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/self/elision/ref-mut-struct.rs b/tests/ui/self/elision/ref-mut-struct.rs
index ca8bd8da133..6bfdca62bca 100644
--- a/tests/ui/self/elision/ref-mut-struct.rs
+++ b/tests/ui/self/elision/ref-mut-struct.rs
@@ -1,4 +1,5 @@
-#![allow(non_snake_case)]
+//@ run-rustfix
+#![allow(non_snake_case, dead_code)]
 
 use std::pin::Pin;
 
diff --git a/tests/ui/self/elision/ref-mut-struct.stderr b/tests/ui/self/elision/ref-mut-struct.stderr
index 26dcfcb6dd0..19b09272504 100644
--- a/tests/ui/self/elision/ref-mut-struct.stderr
+++ b/tests/ui/self/elision/ref-mut-struct.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct.rs:11:9
+  --> $DIR/ref-mut-struct.rs:12:9
    |
 LL |     fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
    |                         -               - let's call the lifetime of this reference `'1`
@@ -14,7 +14,7 @@ LL |     fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &'a u32 {
    |                  ++++        ++                 ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct.rs:16:9
+  --> $DIR/ref-mut-struct.rs:17:9
    |
 LL |     fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
    |                                 -                - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |     fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &'a u32
    |                      ++++            ++                  ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct.rs:21:9
+  --> $DIR/ref-mut-struct.rs:22:9
    |
 LL |     fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
    |                                 -                - let's call the lifetime of this reference `'1`
@@ -44,7 +44,7 @@ LL |     fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &'a u32
    |                      ++++            ++                  ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct.rs:26:9
+  --> $DIR/ref-mut-struct.rs:27:9
    |
 LL |     fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
    |                                         -                 - let's call the lifetime of this reference `'1`
@@ -59,7 +59,7 @@ LL |     fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -
    |                          ++++                ++                   ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-mut-struct.rs:31:9
+  --> $DIR/ref-mut-struct.rs:32:9
    |
 LL |     fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
    |                                         -                 - let's call the lifetime of this reference `'1`
diff --git a/tests/ui/self/elision/ref-self.fixed b/tests/ui/self/elision/ref-self.fixed
new file mode 100644
index 00000000000..41b11c2d77a
--- /dev/null
+++ b/tests/ui/self/elision/ref-self.fixed
@@ -0,0 +1,59 @@
+//@ run-rustfix
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case, dead_code)]
+
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::pin::Pin;
+
+struct Struct {}
+
+struct Wrap<T, P>(T, PhantomData<P>);
+
+impl<T, P> Deref for Wrap<T, P> {
+    type Target = T;
+    fn deref(&self) -> &T { &self.0 }
+}
+
+impl Struct {
+    // Test using `&self` sugar:
+
+    fn ref_self<'a>(&'a self, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    // Test using `&Self` explicitly:
+
+    fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &'a u8 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/self/elision/ref-self.rs b/tests/ui/self/elision/ref-self.rs
index dd07fe1b00b..9b204e2a43b 100644
--- a/tests/ui/self/elision/ref-self.rs
+++ b/tests/ui/self/elision/ref-self.rs
@@ -1,11 +1,12 @@
+//@ run-rustfix
 #![feature(arbitrary_self_types)]
-#![allow(non_snake_case)]
+#![allow(non_snake_case, dead_code)]
 
 use std::marker::PhantomData;
 use std::ops::Deref;
 use std::pin::Pin;
 
-struct Struct { }
+struct Struct {}
 
 struct Wrap<T, P>(T, PhantomData<P>);
 
diff --git a/tests/ui/self/elision/ref-self.stderr b/tests/ui/self/elision/ref-self.stderr
index 8654032b047..b17667827bb 100644
--- a/tests/ui/self/elision/ref-self.stderr
+++ b/tests/ui/self/elision/ref-self.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:21:9
+  --> $DIR/ref-self.rs:22:9
    |
 LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                 -         - let's call the lifetime of this reference `'1`
@@ -14,7 +14,7 @@ LL |     fn ref_self<'a>(&'a self, f: &'a u32) -> &'a u32 {
    |                ++++  ++           ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:28:9
+  --> $DIR/ref-self.rs:29:9
    |
 LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                       -         - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |     fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &'a u32 {
    |                ++++        ++           ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:33:9
+  --> $DIR/ref-self.rs:34:9
    |
 LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                               -          - let's call the lifetime of this reference `'1`
@@ -44,7 +44,7 @@ LL |     fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &'a u32 {
    |                    ++++            ++            ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:38:9
+  --> $DIR/ref-self.rs:39:9
    |
 LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                               -          - let's call the lifetime of this reference `'1`
@@ -59,7 +59,7 @@ LL |     fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &'a u32 {
    |                    ++++            ++            ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:43:9
+  --> $DIR/ref-self.rs:44:9
    |
 LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                       -           - let's call the lifetime of this reference `'1`
@@ -74,7 +74,7 @@ LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &'a u3
    |                        ++++                ++             ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:48:9
+  --> $DIR/ref-self.rs:49:9
    |
 LL |     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                       -           - let's call the lifetime of this reference `'1`
@@ -89,7 +89,7 @@ LL |     fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &'a u3
    |                        ++++                ++             ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:53:9
+  --> $DIR/ref-self.rs:54:9
    |
 LL |     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
    |                                      -                - let's call the lifetime of this reference `'1`
diff --git a/tests/ui/self/elision/ref-struct.fixed b/tests/ui/self/elision/ref-struct.fixed
new file mode 100644
index 00000000000..1c26c84c088
--- /dev/null
+++ b/tests/ui/self/elision/ref-struct.fixed
@@ -0,0 +1,37 @@
+//@ run-rustfix
+#![allow(non_snake_case, dead_code)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+impl Struct {
+    // Test using `&Struct` explicitly:
+
+    fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+
+    fn box_pin_Struct<'a>(self: Box<Pin<&'a Struct>>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/self/elision/ref-struct.rs b/tests/ui/self/elision/ref-struct.rs
index 13a42cd1aed..78b894765aa 100644
--- a/tests/ui/self/elision/ref-struct.rs
+++ b/tests/ui/self/elision/ref-struct.rs
@@ -1,4 +1,5 @@
-#![allow(non_snake_case)]
+//@ run-rustfix
+#![allow(non_snake_case, dead_code)]
 
 use std::pin::Pin;
 
diff --git a/tests/ui/self/elision/ref-struct.stderr b/tests/ui/self/elision/ref-struct.stderr
index 653ecc612d5..157e0d40793 100644
--- a/tests/ui/self/elision/ref-struct.stderr
+++ b/tests/ui/self/elision/ref-struct.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-struct.rs:11:9
+  --> $DIR/ref-struct.rs:12:9
    |
 LL |     fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                         -           - let's call the lifetime of this reference `'1`
@@ -14,7 +14,7 @@ LL |     fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &'a u32 {
    |                  ++++        ++             ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct.rs:16:9
+  --> $DIR/ref-struct.rs:17:9
    |
 LL |     fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
    |                                 -            - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |     fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &'a u32 {
    |                      ++++            ++              ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct.rs:21:9
+  --> $DIR/ref-struct.rs:22:9
    |
 LL |     fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
    |                                 -            - let's call the lifetime of this reference `'1`
@@ -44,7 +44,7 @@ LL |     fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &'a u32 {
    |                      ++++            ++              ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct.rs:26:9
+  --> $DIR/ref-struct.rs:27:9
    |
 LL |     fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
    |                                         -             - let's call the lifetime of this reference `'1`
@@ -59,7 +59,7 @@ LL |     fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &'
    |                          ++++                ++               ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-struct.rs:31:9
+  --> $DIR/ref-struct.rs:32:9
    |
 LL |     fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
    |                                     -             - let's call the lifetime of this reference `'1`