about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTaiki Endo <te316e89@gmail.com>2019-05-27 22:06:08 +0900
committerNiko Matsakis <niko@alum.mit.edu>2019-06-28 10:55:17 -0400
commit7ddc394605b684fbffd4636ca8cd71a3cee6f7dc (patch)
tree0487e9ee1322f814432c4e9de4f0db1bebd8ddac
parent5c7e4c7018357e745943f6b472c8ea4e9da26d28 (diff)
downloadrust-7ddc394605b684fbffd4636ca8cd71a3cee6f7dc.tar.gz
rust-7ddc394605b684fbffd4636ca8cd71a3cee6f7dc.zip
Remove query for `.pin_type()`
-rw-r--r--src/librustc/middle/resolve_lifetime.rs66
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime.rs2
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs5
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr10
4 files changed, 47 insertions, 36 deletions
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 89f5342c4e7..8ab77effcf1 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 668aaf7166a..ba574eeb460 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 3ed5e6bdd72..fc5f94201b8 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 6e345b03056..3296e14f806 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