]> git.lizzy.rs Git - rust.git/commitdiff
Generate `DefId`s for the impl trait of `async` functions
authorOliver Schneider <github35764891676564198441@oli-obk.de>
Tue, 26 Jun 2018 09:56:24 +0000 (11:56 +0200)
committerOliver Schneider <github35764891676564198441@oli-obk.de>
Wed, 27 Jun 2018 09:17:55 +0000 (11:17 +0200)
src/librustc/hir/lowering.rs
src/librustc/hir/map/def_collector.rs
src/librustc_resolve/lib.rs
src/libsyntax/ast.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs

index b7260dded920ed301e22ce329b3a7be04caaa5a4..004121147d904762135009d4f0876339c94167b4 100644 (file)
@@ -863,7 +863,7 @@ fn make_async_expr(
 
         let capture_clause = self.lower_capture_clause(capture_clause);
         let closure_hir_id = self.lower_node_id(closure_node_id).hir_id;
-        let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, false);
+        let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, None);
         let generator = hir::Expr {
             id: closure_node_id,
             hir_id: closure_hir_id,
@@ -1106,7 +1106,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
                                 ),
                                 unsafety: this.lower_unsafety(f.unsafety),
                                 abi: f.abi,
-                                decl: this.lower_fn_decl(&f.decl, None, false, false),
+                                decl: this.lower_fn_decl(&f.decl, None, false, None),
                                 arg_names: this.lower_fn_args_to_names(&f.decl),
                             }))
                         },
@@ -1176,7 +1176,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
                             |this| this.lower_param_bounds(bounds, itctx),
                         )
                     }
-                    ImplTraitContext::Universal(def_id) => {
+                    ImplTraitContext::Universal(_def_id) => {
                         self.lower_node_id(def_node_id);
                         // Add a definition for the in-band TyParam
                         let def_index = self
@@ -1866,18 +1866,18 @@ fn lower_fn_args_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Spanned<Name>
     // decl: the unlowered (ast) function declaration.
     // fn_def_id: if `Some`, impl Trait arguments are lowered into generic parameters on the
     //      given DefId, otherwise impl Trait is disallowed. Must be `Some` if
-    //      make_ret_async is true.
+    //      make_ret_async is also `Some`.
     // impl_trait_return_allow: determines whether impl Trait can be used in return position.
     //      This guards against trait declarations and implementations where impl Trait is
     //      disallowed.
-    // make_ret_async: if enabled, converts `-> T` into `-> impl Future<Output = T>` in the
+    // make_ret_async: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
     //      return type. This is used for `async fn` declarations.
     fn lower_fn_decl(
         &mut self,
         decl: &FnDecl,
         fn_def_id: Option<DefId>,
         impl_trait_return_allow: bool,
-        make_ret_async: bool,
+        make_ret_async: Option<NodeId>,
     ) -> P<hir::FnDecl> {
         let inputs = decl.inputs
             .iter()
@@ -1890,9 +1890,9 @@ fn lower_fn_decl(
             })
             .collect::<HirVec<_>>();
 
-        let output = if make_ret_async {
+        let output = if let Some(ret_id) = make_ret_async {
             self.lower_async_fn_ret_ty(
-                &inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"))
+                &inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"), ret_id)
         } else {
             match decl.output {
                 FunctionRetTy::Ty(ref ty) => match fn_def_id {
@@ -1928,6 +1928,7 @@ fn lower_async_fn_ret_ty(
         inputs: &[P<hir::Ty>],
         output: &FunctionRetTy,
         fn_def_id: DefId,
+        return_impl_trait_id: NodeId,
     ) -> hir::FunctionRetTy {
         // Get lifetimes used in the input arguments to the function. Our output type must also
         // have the same lifetime. FIXME(cramertj) multiple different lifetimes are not allowed
@@ -2079,7 +2080,7 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
         };
 
         let impl_trait_ty = self.lower_existential_impl_trait(
-            span, fn_def_id, |this| {
+            span, fn_def_id, return_impl_trait_id, |this| {
             let output_ty = match output {
                 FunctionRetTy::Ty(ty) =>
                     this.lower_ty(ty, ImplTraitContext::Existential(fn_def_id)),
@@ -2564,9 +2565,9 @@ fn lower_item_kind(
                     // only cares about the input argument patterns in the function
                     // declaration (decl), not the return types.
                     let body_id = this.lower_body(Some(decl), |this| {
-                        if let IsAsync::Async(async_node_id) = header.asyncness {
+                        if let IsAsync::Async { closure_id, .. } = header.asyncness {
                             let async_expr = this.make_async_expr(
-                                CaptureBy::Value, async_node_id, None,
+                                CaptureBy::Value, closure_id, None,
                                 |this| {
                                     let body = this.lower_block(body, false);
                                     this.expr_block(body, ThinVec::new())
@@ -2578,12 +2579,17 @@ fn lower_item_kind(
                         }
                     });
 
+                    let asyncness = match header.asyncness {
+                        IsAsync::Async { return_impl_trait_id, .. } => Some(return_impl_trait_id),
+                        IsAsync::NotAsync => None,
+                    };
+
                     let (generics, fn_decl) = this.add_in_band_defs(
                         generics,
                         fn_def_id,
                         AnonymousLifetimeMode::PassThrough,
                         |this| this.lower_fn_decl(
-                            decl, Some(fn_def_id), true, header.asyncness.is_async())
+                            decl, Some(fn_def_id), true, asyncness)
                     );
 
                     hir::ItemFn(
@@ -2906,7 +2912,7 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
                     AnonymousLifetimeMode::PassThrough,
                     |this| {
                         hir::TraitItemKind::Method(
-                            this.lower_method_sig(sig, trait_item_def_id, false, false),
+                            this.lower_method_sig(sig, trait_item_def_id, false, None),
                             hir::TraitMethod::Required(names),
                         )
                     },
@@ -2924,7 +2930,7 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
                     AnonymousLifetimeMode::PassThrough,
                     |this| {
                         hir::TraitItemKind::Method(
-                            this.lower_method_sig(sig, trait_item_def_id, false, false),
+                            this.lower_method_sig(sig, trait_item_def_id, false, None),
                             hir::TraitMethod::Provided(body_id),
                         )
                     },
@@ -2995,9 +3001,9 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
             }
             ImplItemKind::Method(ref sig, ref body) => {
                 let body_id = self.lower_body(Some(&sig.decl), |this| {
-                    if let IsAsync::Async(async_node_id) = sig.header.asyncness {
+                    if let IsAsync::Async { closure_id, .. } = sig.header.asyncness {
                         let async_expr = this.make_async_expr(
-                            CaptureBy::Value, async_node_id, None,
+                            CaptureBy::Value, closure_id, None,
                             |this| {
                                 let body = this.lower_block(body, false);
                                 this.expr_block(body, ThinVec::new())
@@ -3010,6 +3016,11 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
                 });
                 let impl_trait_return_allow = !self.is_in_trait_impl;
 
+                let asyncness = match sig.header.asyncness {
+                    IsAsync::Async { return_impl_trait_id, .. } => Some(return_impl_trait_id),
+                    IsAsync::NotAsync => None,
+                };
+
                 self.add_in_band_defs(
                     &i.generics,
                     impl_item_def_id,
@@ -3020,7 +3031,7 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
                                 sig,
                                 impl_item_def_id,
                                 impl_trait_return_allow,
-                                sig.header.asyncness.is_async(),
+                                asyncness,
                             ),
                             body_id,
                         )
@@ -3100,8 +3111,8 @@ fn visit_path_segment(
                 path_span: Span,
                 path_segment: &'v PathSegment,
             ) {
-                if let Some(ref p) = path_segment.parameters {
-                    if let PathParameters::Parenthesized(..) = **p {
+                if let Some(ref p) = path_segment.args {
+                    if let GenericArgs::Parenthesized(_) = **p {
                         return;
                     }
                 }
@@ -3123,8 +3134,11 @@ fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
                 vec
             }
             ItemKind::MacroDef(..) => SmallVector::new(),
-            ItemKind::Fn(ref decl, ..) => {
+            ItemKind::Fn(ref decl, ref header, ..) => {
                 let mut ids = SmallVector::one(hir::ItemId { id: i.id });
+                if let IsAsync::Async { return_impl_trait_id, .. } = header.asyncness {
+                    ids.push(hir::ItemId { id: return_impl_trait_id });
+                }
                 self.lower_impl_trait_ids(decl, &mut ids);
                 ids
             },
@@ -3132,6 +3146,9 @@ fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
                 let mut ids = SmallVector::one(hir::ItemId { id: i.id });
                 for item in items {
                     if let ImplItemKind::Method(ref sig, _) = item.node {
+                        if let IsAsync::Async { return_impl_trait_id, .. } = sig.header.asyncness {
+                            ids.push(hir::ItemId { id: return_impl_trait_id });
+                        }
                         self.lower_impl_trait_ids(&sig.decl, &mut ids);
                     }
                 }
@@ -3214,7 +3231,7 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
                         |this| {
                             (
                                 // Disallow impl Trait in foreign items
-                                this.lower_fn_decl(fdec, None, false, false),
+                                this.lower_fn_decl(fdec, None, false, None),
                                 this.lower_fn_args_to_names(fdec),
                             )
                         },
@@ -3238,7 +3255,7 @@ fn lower_method_sig(
         sig: &MethodSig,
         fn_def_id: DefId,
         impl_trait_return_allow: bool,
-        is_async: bool,
+        is_async: Option<NodeId>,
     ) -> hir::MethodSig {
         hir::MethodSig {
             header: self.lower_fn_header(sig.header),
@@ -3278,7 +3295,7 @@ fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
 
     fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
         match a {
-            IsAsync::Async(_) => hir::IsAsync::Async,
+            IsAsync::Async { .. } => hir::IsAsync::Async,
             IsAsync::NotAsync => hir::IsAsync::NotAsync,
         }
     }
@@ -3581,7 +3598,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
             ExprKind::Closure(
                 capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
             ) => {
-                if let IsAsync::Async(async_closure_node_id) = asyncness {
+                if let IsAsync::Async { async_closure_node_id, .. } = asyncness {
                     let outer_decl = FnDecl {
                         inputs: decl.inputs.clone(),
                         output: FunctionRetTy::Default(fn_decl_span),
@@ -3590,7 +3607,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     // We need to lower the declaration outside the new scope, because we
                     // have to conserve the state of being inside a loop condition for the
                     // closure argument types.
-                    let fn_decl = self.lower_fn_decl(&outer_decl, None, false, false);
+                    let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
 
                     self.with_new_scopes(|this| {
                         // FIXME(cramertj) allow `async` non-`move` closures with
@@ -3617,7 +3634,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                                 Some(&**ty)
                             } else { None };
                             let async_body = this.make_async_expr(
-                                capture_clause, async_closure_node_id, async_ret_ty,
+                                capture_clause, closure_id, async_ret_ty,
                                 |this| {
                                     this.with_new_scopes(|this| this.lower_expr(body))
                                 });
@@ -3633,7 +3650,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     })
                 } else {
                     // Lower outside new scope to preserve `is_in_loop_condition`.
-                    let fn_decl = self.lower_fn_decl(decl, None, false, false);
+                    let fn_decl = self.lower_fn_decl(decl, None, false, None);
 
                     self.with_new_scopes(|this| {
                         let mut is_generator = false;
index 4884d4407577a38fb4ac702f5bdf129ee7689e72..47ebc97310213505bde1127b0a00983ef3ebaea4 100644 (file)
@@ -77,6 +77,7 @@ 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>)
@@ -86,6 +87,7 @@ fn visit_async_fn(
         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,
                                   DefPathData::ClosureExpr,
                                   REGULAR_SPACE,
@@ -120,10 +122,14 @@ 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(async_node_id), .. }, ..) => {
+            ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async {
+                closure_id,
+                return_impl_trait_id,
+            }, .. }, ..) => {
                 return self.visit_async_fn(
                     i.id,
-                    async_node_id,
+                    closure_id,
+                    return_impl_trait_id,
                     i.ident.name,
                     i.span,
                     |this| visit::walk_item(this, i)
@@ -228,11 +234,15 @@ 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(async_node_id), .. }, ..
+                header: FnHeader { asyncness: IsAsync::Async {
+                    closure_id,
+                    return_impl_trait_id,
+                }, .. }, ..
             }, ..) => {
                 return self.visit_async_fn(
                     ii.id,
-                    async_node_id,
+                    closure_id,
+                    return_impl_trait_id,
                     ii.ident.name,
                     ii.span,
                     |this| visit::walk_impl_item(this, ii)
@@ -277,8 +287,8 @@ fn visit_expr(&mut self, expr: &'a Expr) {
 
                 // Async closures desugar to closures inside of closures, so
                 // we must create two defs.
-                if let IsAsync::Async(async_id) = asyncness {
-                    let async_def = self.create_def(async_id,
+                if let IsAsync::Async { closure_id, .. } = asyncness {
+                    let async_def = self.create_def(closure_id,
                                                     DefPathData::ClosureExpr,
                                                     REGULAR_SPACE,
                                                     expr.span);
index 2052918747b39301f1f14364c7d244b77a7eb00c..159850098434eace4ac963a80b325c887132161c 100644 (file)
@@ -777,8 +777,8 @@ fn visit_fn(&mut self,
         visit::walk_fn_ret_ty(self, &declaration.output);
 
         // Resolve the function body, potentially inside the body of an async closure
-        if let IsAsync::Async(async_closure_id) = asyncness {
-            let rib_kind = ClosureRibKind(async_closure_id);
+        if let IsAsync::Async { closure_id, .. } = asyncness {
+            let rib_kind = ClosureRibKind(closure_id);
             self.ribs[ValueNS].push(Rib::new(rib_kind));
             self.label_ribs.push(Rib::new(rib_kind));
         }
@@ -3935,8 +3935,9 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
             // resolve the arguments within the proper scopes so that usages of them inside the
             // closure are detected as upvars rather than normal closure arg usages.
             ExprKind::Closure(
-                _, IsAsync::Async(inner_closure_id), _, ref fn_decl, ref body, _span) =>
-            {
+                _, IsAsync::Async { closure_id: inner_closure_id, .. }, _,
+                ref fn_decl, ref body, _span,
+            ) => {
                 let rib_kind = ClosureRibKind(expr.id);
                 self.ribs[ValueNS].push(Rib::new(rib_kind));
                 self.label_ribs.push(Rib::new(rib_kind));
index ca07ac7988dfe8b06929a1fd4452eed6bf4439db..d38af6a608866a406e6a5beea7204d91f6288f04 100644 (file)
@@ -1722,13 +1722,16 @@ pub enum Unsafety {
 
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum IsAsync {
-    Async(NodeId),
+    Async {
+        closure_id: NodeId,
+        return_impl_trait_id: NodeId,
+    },
     NotAsync,
 }
 
 impl IsAsync {
     pub fn is_async(self) -> bool {
-        if let IsAsync::Async(_) = self {
+        if let IsAsync::Async { .. } = self {
             true
         } else {
             false
index c813ec1977b881bc00ee8cb3f6379af7f89c9c79..2a21e4c017112687e664e20b303b929547ba0959 100644 (file)
@@ -1726,7 +1726,7 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
                                     "labels on blocks are unstable");
                 }
             }
-            ast::ExprKind::Closure(_, ast::IsAsync::Async(_), ..) => {
+            ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => {
                 gate_feature_post!(&self, async_await, e.span, "async closures are unstable");
             }
             ast::ExprKind::Async(..) => {
index 1035be3a159792825928e916626a4f4fbe03ebc3..d9d3febc4fe4d2312e33df78c4e37d86eaaee4a2 100644 (file)
@@ -100,6 +100,10 @@ fn fold_fn_decl(&mut self, d: P<FnDecl>) -> P<FnDecl> {
         noop_fold_fn_decl(d, self)
     }
 
+    fn fold_asyncness(&mut self, a: IsAsync) -> IsAsync {
+        noop_fold_asyncness(a, self)
+    }
+
     fn fold_block(&mut self, b: P<Block>) -> P<Block> {
         noop_fold_block(b, self)
     }
@@ -669,6 +673,16 @@ pub fn noop_fold_interpolated<T: Folder>(nt: token::Nonterminal, fld: &mut T)
     }
 }
 
+pub fn noop_fold_asyncness<T: Folder>(asyncness: IsAsync, fld: &mut T) -> IsAsync {
+    match asyncness {
+        IsAsync::Async { closure_id, return_impl_trait_id } => IsAsync::Async {
+            closure_id: fld.new_id(closure_id),
+            return_impl_trait_id: fld.new_id(return_impl_trait_id),
+        },
+        IsAsync::NotAsync => IsAsync::NotAsync,
+    }
+}
+
 pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
     decl.map(|FnDecl {inputs, output, variadic}| FnDecl {
         inputs: inputs.move_map(|x| fld.fold_arg(x)),
@@ -996,10 +1010,7 @@ pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T)
 }
 
 pub fn noop_fold_fn_header<T: Folder>(mut header: FnHeader, folder: &mut T) -> FnHeader {
-    header.asyncness = match header.asyncness {
-        IsAsync::Async(node_id) => IsAsync::Async(folder.new_id(node_id)),
-        IsAsync::NotAsync => IsAsync::NotAsync,
-    };
+    header.asyncness = folder.fold_asyncness(header.asyncness);
     header
 }
 
@@ -1249,12 +1260,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                           arms.move_map(|x| folder.fold_arm(x)))
             }
             ExprKind::Closure(capture_clause, asyncness, movability, decl, body, span) => {
-                let asyncness = match asyncness {
-                    IsAsync::Async(node_id) => IsAsync::Async(folder.new_id(node_id)),
-                    IsAsync::NotAsync => IsAsync::NotAsync,
-                };
                 ExprKind::Closure(capture_clause,
-                                  asyncness,
+                                  folder.fold_asyncness(asyncness),
                                   movability,
                                   folder.fold_fn_decl(decl),
                                   folder.fold_expr(body),
@@ -1265,7 +1272,11 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                                 opt_label.map(|label| folder.fold_label(label)))
             }
             ExprKind::Async(capture_clause, node_id, body) => {
-                ExprKind::Async(capture_clause, folder.new_id(node_id), folder.fold_block(body))
+                ExprKind::Async(
+                    capture_clause,
+                    folder.new_id(node_id),
+                    folder.fold_block(body),
+                )
             }
             ExprKind::Assign(el, er) => {
                 ExprKind::Assign(folder.fold_expr(el), folder.fold_expr(er))
index 8690918c805253b93e5681d2e8a2f47a7b4ba008..4c86a64b0997b4c18fe432fb8f7a9539bad6d0aa 100644 (file)
@@ -1299,7 +1299,10 @@ fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a,
     /// Parse asyncness: `async` or nothing
     fn parse_asyncness(&mut self) -> IsAsync {
         if self.eat_keyword(keywords::Async) {
-            IsAsync::Async(ast::DUMMY_NODE_ID)
+            IsAsync::Async {
+                closure_id: ast::DUMMY_NODE_ID,
+                return_impl_trait_id: ast::DUMMY_NODE_ID,
+            }
         } else {
             IsAsync::NotAsync
         }
@@ -3279,10 +3282,8 @@ fn parse_lambda_expr(&mut self,
         } else {
             Movability::Movable
         };
-        let asyncness = if self.span.edition() >= Edition::Edition2018
-            && self.eat_keyword(keywords::Async)
-        {
-            IsAsync::Async(ast::DUMMY_NODE_ID)
+        let asyncness = if self.span.edition() >= Edition::Edition2018 {
+            self.parse_asyncness()
         } else {
             IsAsync::NotAsync
         };
@@ -6798,7 +6799,10 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
             let fn_span = self.prev_span;
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(unsafety,
-                                   IsAsync::Async(ast::DUMMY_NODE_ID),
+                                   IsAsync::Async {
+                                       closure_id: ast::DUMMY_NODE_ID,
+                                       return_impl_trait_id: ast::DUMMY_NODE_ID,
+                                   },
                                    respan(fn_span, Constness::NotConst),
                                    Abi::Rust)?;
             let prev_span = self.prev_span;