]> git.lizzy.rs Git - rust.git/commitdiff
Allow named lifetimes in async functions.
authorJakub Kozlowski <mail@jakub-kozlowski.com>
Thu, 6 Sep 2018 18:01:49 +0000 (19:01 +0100)
committerJakub Kozlowski <mail@jakub-kozlowski.com>
Thu, 6 Sep 2018 18:02:51 +0000 (19:02 +0100)
- Fixes #53174

src/librustc/hir/map/def_collector.rs
src/test/run-pass/async-await.rs

index cab620aeec548317a71eff72c2065a0f67b56f0a..b80c7445624e53f024b21c7071ad419b8865faf0 100644 (file)
@@ -76,23 +76,38 @@ pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F)
     fn visit_async_fn(
         &mut self,
         id: NodeId,
-        async_node_id: NodeId,
-        return_impl_trait_id: NodeId,
         name: Name,
         span: Span,
-        visit_fn: impl FnOnce(&mut DefCollector<'a>)
+        header: &FnHeader,
+        generics: &'a Generics,
+        decl: &'a FnDecl,
+        body: &'a Block,
     ) {
+        let (closure_id, return_impl_trait_id) = match header.asyncness {
+            IsAsync::Async {
+                closure_id,
+                return_impl_trait_id,
+            } => (closure_id, return_impl_trait_id),
+            _ => unreachable!(),
+        };
+
         // For async functions, we need to create their inner defs inside of a
         // closure to match their desugared representation.
         let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
         let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span);
         return self.with_parent(fn_def, |this| {
             this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span);
-            let closure_def = this.create_def(async_node_id,
+
+            visit::walk_generics(this, generics);
+            visit::walk_fn_decl(this, decl);
+
+            let closure_def = this.create_def(closure_id,
                                   DefPathData::ClosureExpr,
                                   REGULAR_SPACE,
                                   span);
-            this.with_parent(closure_def, visit_fn)
+            this.with_parent(closure_def, |this| {
+                visit::walk_block(this, body);
+            })
         })
     }
 
@@ -122,17 +137,20 @@ fn visit_item(&mut self, i: &'a Item) {
             ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
                 return visit::walk_item(self, i);
             }
-            ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async {
-                closure_id,
-                return_impl_trait_id,
-            }, .. }, ..) => {
+            ItemKind::Fn(
+                ref decl,
+                ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
+                ref generics,
+                ref body,
+            ) => {
                 return self.visit_async_fn(
                     i.id,
-                    closure_id,
-                    return_impl_trait_id,
                     i.ident.name,
                     i.span,
-                    |this| visit::walk_item(this, i)
+                    header,
+                    generics,
+                    decl,
+                    body,
                 )
             }
             ItemKind::Mod(..) => DefPathData::Module(i.ident.as_interned_str()),
@@ -233,18 +251,17 @@ fn visit_trait_item(&mut self, ti: &'a TraitItem) {
     fn visit_impl_item(&mut self, ii: &'a ImplItem) {
         let def_data = match ii.node {
             ImplItemKind::Method(MethodSig {
-                header: FnHeader { asyncness: IsAsync::Async {
-                    closure_id,
-                    return_impl_trait_id,
-                }, .. }, ..
-            }, ..) => {
+                header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
+                ref decl,
+            }, ref body) => {
                 return self.visit_async_fn(
                     ii.id,
-                    closure_id,
-                    return_impl_trait_id,
                     ii.ident.name,
                     ii.span,
-                    |this| visit::walk_impl_item(this, ii)
+                    header,
+                    &ii.generics,
+                    decl,
+                    body,
                 )
             }
             ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
@@ -341,4 +358,4 @@ fn visit_token(&mut self, t: Token) {
             }
         }
     }
-}
+}
\ No newline at end of file
index 46f228459079a25806ebd417e607754e52dac171..9d004ea4574bae30023c4e37b8b662dd86585660 100644 (file)
@@ -67,6 +67,13 @@ fn async_block(x: u8) -> impl Future<Output = u8> {
     }
 }
 
+fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a {
+    async move {
+        await!(wake_and_yield_once());
+        *x
+    }  
+}
+
 fn async_nonmove_block(x: u8) -> impl Future<Output = u8> {
     async move {
         let future = async {
@@ -94,6 +101,23 @@ async fn async_fn_with_borrow(x: &u8) -> u8 {
     *x
 }
 
+async fn async_fn_with_borrow_named_lifetime<'a>(x: &'a u8) -> u8 {
+    await!(wake_and_yield_once());
+    *x
+}
+
+fn async_fn_with_impl_future_named_lifetime<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a {
+    async move {
+        await!(wake_and_yield_once());
+        *x
+    }
+}
+
+async fn async_fn_with_named_lifetime_multiple_args<'a>(x: &'a u8, _y: &'a u8) -> u8 {
+    await!(wake_and_yield_once());
+    *x   
+}
+
 fn async_fn_with_internal_borrow(y: u8) -> impl Future<Output = u8> {
     async move {
         await!(async_fn_with_borrow(&y))
@@ -138,16 +162,43 @@ fn test_future_yields_once_then_returns<F, Fut>(f: F)
 
 fn main() {
     macro_rules! test {
-        ($($fn_name:ident,)*) => { $(
+        ($($fn_name:expr,)*) => { $(
             test_future_yields_once_then_returns($fn_name);
         )* }
     }
 
+    macro_rules! test_with_borrow {
+        ($($fn_name:expr,)*) => { $(
+            test_future_yields_once_then_returns(|x| { 
+                async move {
+                    await!($fn_name(&x))
+                }
+            });
+        )* }
+    }
+
     test! {
         async_block,
         async_nonmove_block,
         async_closure,
         async_fn,
         async_fn_with_internal_borrow,
+        |x| { 
+            async move { 
+                unsafe { await!(unsafe_async_fn(x)) } 
+            } 
+        },  
+    }
+
+    test_with_borrow! {
+        async_block_with_borrow_named_lifetime,
+        async_fn_with_borrow,
+        async_fn_with_borrow_named_lifetime,
+        async_fn_with_impl_future_named_lifetime,
+        |x| { 
+            async move {
+                await!(async_fn_with_named_lifetime_multiple_args(x, x))
+            }
+        },
     }
 }