From 5c7e4c7018357e745943f6b472c8ea4e9da26d28 Mon Sep 17 00:00:00 2001 From: Taiki Endo 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>> { self } + + fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self } + + fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self } +} + +type Alias = Pin; +impl Foo { + fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } +} + +struct Bar { + field1: T, + field2: U, +} + +impl Bar { + 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>; +} + +struct Baz(Vec); + +impl AsyncBufRead for Baz { + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) + -> Poll> + { + 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 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, + } + + 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 = Pin; impl Foo { - fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self } } struct Bar { 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 = Pin; +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 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, + } + + 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, + 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 Date: Wed, 29 May 2019 18:50:24 +0900 Subject: [PATCH 4/5] Use Set1 instead of Option --- 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, + lifetime: Set1, } 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 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 +