From 5c7e4c7018357e745943f6b472c8ea4e9da26d28 Mon Sep 17 00:00:00 2001
From: Taiki Endo <te316e89@gmail.com>
Date: Mon, 27 May 2019 01:43:12 +0900
Subject: [PATCH 1/5] Allow lifetime elision in `Pin<&(mut) Self>`

---
 src/librustc/middle/resolve_lifetime.rs       | 29 ++++++++-
 .../self/arbitrary_self_types_pin_lifetime.rs | 60 +++++++++++++++++++
 ...rary_self_types_pin_lifetime_impl_trait.rs | 13 ++++
 ..._self_types_pin_lifetime_impl_trait.stderr | 20 +++++++
 ...itrary_self_types_pin_lifetime_mismatch.rs | 13 ++++
 ...ry_self_types_pin_lifetime_mismatch.stderr | 18 ++++++
 src/test/ui/self/self_lifetime.rs             | 13 ++++
 7 files changed, 165 insertions(+), 1 deletion(-)
 create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime.rs
 create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs
 create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
 create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
 create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
 create mode 100644 src/test/ui/self/self_lifetime.rs

diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 2402d0eefde48..89f5342c4e7b6 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -2154,7 +2154,34 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 false
             };
 
-            if let hir::TyKind::Rptr(lifetime_ref, ref mt) = inputs[0].node {
+            let mut self_arg = &inputs[0].node;
+
+            // Apply `self: &(mut) Self` elision rules even if nested in `Pin`.
+            loop {
+                if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = *self_arg {
+                    if let Res::Def(DefKind::Struct, def_id) = path.res {
+                        if self.tcx.lang_items().pin_type() == Some(def_id) {
+                            if let Some(args) = path
+                                .segments
+                                .last()
+                                .and_then(|segment| segment.args.as_ref())
+                            {
+                                if args.args.len() == 1 {
+                                    if let GenericArg::Type(ty) = &args.args[0] {
+                                        self_arg = &ty.node;
+                                        // Keep dereferencing `self_arg` until we get to non-`Pin`
+                                        // types.
+                                        continue;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+
+            if let hir::TyKind::Rptr(lifetime_ref, ref mt) = *self_arg {
                 if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = mt.ty.node {
                     if is_self_ty(path.res) {
                         if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs
new file mode 100644
index 0000000000000..668aaf7166a0f
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs
@@ -0,0 +1,60 @@
+// compile-pass
+
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+struct Foo;
+
+impl Foo {
+    fn pin_ref(self: Pin<&Self>) -> Pin<&Self> { self }
+
+    fn pin_mut(self: Pin<&mut Self>) -> Pin<&mut Self> { self }
+
+    fn pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> Pin<Pin<Pin<&Self>>> { self }
+
+    fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self }
+
+    fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self }
+}
+
+type Alias<T> = Pin<T>;
+impl Foo {
+    fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+}
+
+struct Bar<T: Unpin, U: Unpin> {
+    field1: T,
+    field2: U,
+}
+
+impl<T: Unpin, U: Unpin> Bar<T, U> {
+    fn fields(self: Pin<&mut Self>) -> (Pin<&mut T>, Pin<&mut U>) {
+        let this = self.get_mut();
+        (Pin::new(&mut this.field1), Pin::new(&mut this.field2))
+    }
+}
+
+trait AsyncBufRead {
+    fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>)
+        -> Poll<std::io::Result<&[u8]>>;
+}
+
+struct Baz(Vec<u8>);
+
+impl AsyncBufRead for Baz {
+    fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>)
+        -> Poll<std::io::Result<&[u8]>>
+    {
+        Poll::Ready(Ok(&self.get_mut().0))
+    }
+}
+
+fn main() {
+    let mut foo = Foo;
+    { Pin::new(&foo).pin_ref() };
+    { Pin::new(&mut foo).pin_mut() };
+    { Pin::new(Pin::new(Pin::new(&foo))).pin_pin_pin_ref() };
+    { Pin::new(&foo).pin_ref_impl_trait() };
+    let mut bar = Bar { field1: 0u8, field2: 1u8 };
+    { Pin::new(&mut bar).fields() };
+}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs
new file mode 100644
index 0000000000000..ad8959727cbee
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs
@@ -0,0 +1,13 @@
+// compile-fail
+
+use std::pin::Pin;
+
+struct Foo;
+
+impl Foo {
+    fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR cannot infer an appropriate lifetime
+}
+
+fn main() {
+    { Pin::new(&Foo).f() };
+}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
new file mode 100644
index 0000000000000..5118280e7ec0c
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
@@ -0,0 +1,20 @@
+error: cannot infer an appropriate lifetime
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:8:44
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
+   |                               ----------   ^^^^ ...but this borrow...
+   |                               |
+   |                               this return type evaluates to the `'static` lifetime...
+   |
+note: ...can't outlive the anonymous lifetime #1 defined on the method body at 8:5
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:8:5
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 8:5
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
+   |                               ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
new file mode 100644
index 0000000000000..3ed5e6bdd7211
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
@@ -0,0 +1,13 @@
+// compile-fail
+
+use std::pin::Pin;
+
+struct Foo;
+
+impl Foo {
+    fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } //~ ERROR E0623
+
+    fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } //~ ERROR E0623
+}
+
+fn main() {}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
new file mode 100644
index 0000000000000..6e345b03056e9
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
@@ -0,0 +1,18 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:46
+   |
+LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+   |                              ----     ----   ^ ...but data from `f` is returned here
+   |                              |
+   |                              this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:10:76
+   |
+LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |                               ----              -----------------          ^ ...but data from `f` is returned here
+   |                               |
+   |                               this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/self/self_lifetime.rs b/src/test/ui/self/self_lifetime.rs
new file mode 100644
index 0000000000000..a3163ade0404f
--- /dev/null
+++ b/src/test/ui/self/self_lifetime.rs
@@ -0,0 +1,13 @@
+// compile-pass
+
+struct Foo<'a>(&'a ());
+impl<'a> Foo<'a> {
+    fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
+}
+
+type Alias = Foo<'static>;
+impl Alias {
+    fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
+}
+
+fn main() {}

From 7ddc394605b684fbffd4636ca8cd71a3cee6f7dc Mon Sep 17 00:00:00 2001
From: Taiki Endo <te316e89@gmail.com>
Date: Mon, 27 May 2019 22:06:08 +0900
Subject: [PATCH 2/5] Remove query for `.pin_type()`

---
 src/librustc/middle/resolve_lifetime.rs       | 66 +++++++++----------
 .../self/arbitrary_self_types_pin_lifetime.rs |  2 +-
 ...itrary_self_types_pin_lifetime_mismatch.rs |  5 ++
 ...ry_self_types_pin_lifetime_mismatch.stderr | 10 ++-
 4 files changed, 47 insertions(+), 36 deletions(-)

diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 89f5342c4e7b6..8ab77effcf1e7 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -2154,46 +2154,44 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 false
             };
 
-            let mut self_arg = &inputs[0].node;
-
-            // Apply `self: &(mut) Self` elision rules even if nested in `Pin`.
-            loop {
-                if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = *self_arg {
-                    if let Res::Def(DefKind::Struct, def_id) = path.res {
-                        if self.tcx.lang_items().pin_type() == Some(def_id) {
-                            if let Some(args) = path
-                                .segments
-                                .last()
-                                .and_then(|segment| segment.args.as_ref())
-                            {
-                                if args.args.len() == 1 {
-                                    if let GenericArg::Type(ty) = &args.args[0] {
-                                        self_arg = &ty.node;
-                                        // Keep dereferencing `self_arg` until we get to non-`Pin`
-                                        // types.
-                                        continue;
-                                    }
-                                }
+            struct SelfVisitor<'a, F: FnMut(Res) -> bool> {
+                is_self_ty: F,
+                map: &'a NamedRegionMap,
+                lifetime: Option<Region>,
+            }
+
+            impl<'a, F: FnMut(Res) -> bool> Visitor<'a> for SelfVisitor<'a, F> {
+                fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
+                    NestedVisitorMap::None
+                }
+
+                fn visit_ty(&mut self, ty: &'a hir::Ty) {
+                    if let hir::TyKind::Rptr(lifetime_ref, ref mt) = ty.node {
+                        if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = mt.ty.node
+                        {
+                            if (self.is_self_ty)(path.res) {
+                                self.lifetime = self.map.defs.get(&lifetime_ref.hir_id).copied();
+                                return;
                             }
                         }
                     }
+                    intravisit::walk_ty(self, ty)
                 }
-                break;
             }
 
-            if let hir::TyKind::Rptr(lifetime_ref, ref mt) = *self_arg {
-                if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = mt.ty.node {
-                    if is_self_ty(path.res) {
-                        if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
-                            let scope = Scope::Elision {
-                                elide: Elide::Exact(lifetime),
-                                s: self.scope,
-                            };
-                            self.with(scope, |_, this| this.visit_ty(output));
-                            return;
-                        }
-                    }
-                }
+            let mut visitor = SelfVisitor {
+                is_self_ty,
+                map: self.map,
+                lifetime: None,
+            };
+            visitor.visit_ty(&inputs[0]);
+            if let Some(lifetime) = visitor.lifetime {
+                let scope = Scope::Elision {
+                    elide: Elide::Exact(lifetime),
+                    s: self.scope,
+                };
+                self.with(scope, |_, this| this.visit_ty(output));
+                return;
             }
         }
 
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs
index 668aaf7166a0f..ba574eeb4609b 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs
@@ -19,7 +19,7 @@ impl Foo {
 
 type Alias<T> = Pin<T>;
 impl Foo {
-    fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+    fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self }
 }
 
 struct Bar<T: Unpin, U: Unpin> {
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
index 3ed5e6bdd7211..fc5f94201b81a 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
@@ -10,4 +10,9 @@ impl Foo {
     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } //~ ERROR E0623
 }
 
+type Alias<T> = Pin<T>;
+impl Foo {
+    fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } //~ ERROR E0623
+}
+
 fn main() {}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
index 6e345b03056e9..3296e14f806e1 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
@@ -14,5 +14,13 @@ LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self,
    |                               |
    |                               this parameter and the return type are declared with different lifetimes...
 
-error: aborting due to 2 previous errors
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:15:58
+   |
+LL |     fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+   |                                         ------     ---   ^^^ ...but data from `arg` is returned here
+   |                                         |
+   |                                         this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 3 previous errors
 

From 3d0d96bd7b6d382ba25a237f4954ec4e6ade081c Mon Sep 17 00:00:00 2001
From: Taiki Endo <te316e89@gmail.com>
Date: Wed, 29 May 2019 17:37:28 +0900
Subject: [PATCH 3/5] Make is_self_ty a method on SelfVisitor

---
 src/librustc/middle/resolve_lifetime.rs | 67 +++++++++++++------------
 1 file changed, 35 insertions(+), 32 deletions(-)

diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 8ab77effcf1e7..c901ce1de5785 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -2126,41 +2126,44 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         // First (determined here), if `self` is by-reference, then the
         // implied output region is the region of the self parameter.
         if has_self {
-            // Look for `self: &'a Self` - also desugared from `&'a self`,
-            // and if that matches, use it for elision and return early.
-            let is_self_ty = |res: Res| {
-                if let Res::SelfTy(..) = res {
-                    return true;
-                }
-
-                // Can't always rely on literal (or implied) `Self` due
-                // to the way elision rules were originally specified.
-                let impl_self = impl_self.map(|ty| &ty.node);
-                if let Some(&hir::TyKind::Path(hir::QPath::Resolved(None, ref path))) = impl_self {
-                    match path.res {
-                        // Whitelist the types that unambiguously always
-                        // result in the same type constructor being used
-                        // (it can't differ between `Self` and `self`).
-                        Res::Def(DefKind::Struct, _)
-                        | Res::Def(DefKind::Union, _)
-                        | Res::Def(DefKind::Enum, _)
-                        | Res::PrimTy(_) => {
-                            return res == path.res
-                        }
-                        _ => {}
+            struct SelfVisitor<'a> {
+                map: &'a NamedRegionMap,
+                impl_self: Option<&'a hir::TyKind>,
+                lifetime: Option<Region>,
+            }
+
+            impl SelfVisitor<'_> {
+                // Look for `self: &'a Self` - also desugared from `&'a self`,
+                // and if that matches, use it for elision and return early.
+                fn is_self_ty(&self, res: Res) -> bool {
+                    if let Res::SelfTy(..) = res {
+                        return true;
                     }
-                }
 
-                false
-            };
+                    // Can't always rely on literal (or implied) `Self` due
+                    // to the way elision rules were originally specified.
+                    if let Some(&hir::TyKind::Path(hir::QPath::Resolved(None, ref path))) =
+                        self.impl_self
+                    {
+                        match path.res {
+                            // Whitelist the types that unambiguously always
+                            // result in the same type constructor being used
+                            // (it can't differ between `Self` and `self`).
+                            Res::Def(DefKind::Struct, _)
+                            | Res::Def(DefKind::Union, _)
+                            | Res::Def(DefKind::Enum, _)
+                            | Res::PrimTy(_) => {
+                                return res == path.res
+                            }
+                            _ => {}
+                        }
+                    }
 
-            struct SelfVisitor<'a, F: FnMut(Res) -> bool> {
-                is_self_ty: F,
-                map: &'a NamedRegionMap,
-                lifetime: Option<Region>,
+                    false
+                }
             }
 
-            impl<'a, F: FnMut(Res) -> bool> Visitor<'a> for SelfVisitor<'a, F> {
+            impl<'a> Visitor<'a> for SelfVisitor<'a> {
                 fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
                     NestedVisitorMap::None
                 }
@@ -2169,7 +2172,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     if let hir::TyKind::Rptr(lifetime_ref, ref mt) = ty.node {
                         if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = mt.ty.node
                         {
-                            if (self.is_self_ty)(path.res) {
+                            if self.is_self_ty(path.res) {
                                 self.lifetime = self.map.defs.get(&lifetime_ref.hir_id).copied();
                                 return;
                             }
@@ -2180,8 +2183,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             }
 
             let mut visitor = SelfVisitor {
-                is_self_ty,
                 map: self.map,
+                impl_self: impl_self.map(|ty| &ty.node),
                 lifetime: None,
             };
             visitor.visit_ty(&inputs[0]);

From cef33d4ef9b448d5d088de61189f02184edbeca4 Mon Sep 17 00:00:00 2001
From: Taiki Endo <te316e89@gmail.com>
Date: Wed, 29 May 2019 18:50:24 +0900
Subject: [PATCH 4/5] Use Set1<Region> instead of Option<Region>

---
 src/librustc/middle/resolve_lifetime.rs | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index c901ce1de5785..50715a456ec5f 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -2129,7 +2129,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             struct SelfVisitor<'a> {
                 map: &'a NamedRegionMap,
                 impl_self: Option<&'a hir::TyKind>,
-                lifetime: Option<Region>,
+                lifetime: Set1<Region>,
             }
 
             impl SelfVisitor<'_> {
@@ -2173,8 +2173,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                         if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = mt.ty.node
                         {
                             if self.is_self_ty(path.res) {
-                                self.lifetime = self.map.defs.get(&lifetime_ref.hir_id).copied();
-                                return;
+                                if let Some(lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
+                                    self.lifetime.insert(*lifetime);
+                                }
                             }
                         }
                     }
@@ -2185,10 +2186,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             let mut visitor = SelfVisitor {
                 map: self.map,
                 impl_self: impl_self.map(|ty| &ty.node),
-                lifetime: None,
+                lifetime: Set1::Empty,
             };
             visitor.visit_ty(&inputs[0]);
-            if let Some(lifetime) = visitor.lifetime {
+            if let Set1::One(lifetime) = visitor.lifetime {
                 let scope = Scope::Elision {
                     elide: Elide::Exact(lifetime),
                     s: self.scope,

From 83dc1b52f6709169a00fa7138dd3e908d611a28b Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Fri, 28 Jun 2019 22:30:57 +0200
Subject: [PATCH 5/5] arbitrary_self_types lifetime elision: --bless
 --compare-mode=nll.

---
 ...f_types_pin_lifetime_impl_trait.nll.stderr | 14 ++++++++++
 ...elf_types_pin_lifetime_mismatch.nll.stderr | 28 +++++++++++++++++++
 2 files changed, 42 insertions(+)
 create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr
 create mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr

diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr
new file mode 100644
index 0000000000000..496700781fd37
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:8:31
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
+   |                    -          ^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
+   |                    |
+   |                    let's call the lifetime of this reference `'1`
+help: to allow this impl Trait to capture borrowed data with lifetime `'1`, add `'_` as a constraint
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
+   |                               ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr
new file mode 100644
index 0000000000000..8a0f1a804ad82
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr
@@ -0,0 +1,28 @@
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:46
+   |
+LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+   |                    -         -               ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                    |         |
+   |                    |         let's call the lifetime of this reference `'1`
+   |                    let's call the lifetime of this reference `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:10:69
+   |
+LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |                    -          -                                     ^^^^^^^^^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                    |          |
+   |                    |          let's call the lifetime of this reference `'1`
+   |                    let's call the lifetime of this reference `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:15:58
+   |
+LL |     fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+   |            --  ---- has type `std::pin::Pin<&'1 Foo>`    ^^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+   |            |
+   |            lifetime `'a` defined here
+
+error: aborting due to 3 previous errors
+