From b2e2c321053a1bed9dd3ebf02e440072d797f3e3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 18 Jun 2018 16:23:13 +0200 Subject: Generate the `NodeId` for `existential type` in the AST --- src/libsyntax/parse/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 21bd6c08324..8690918c805 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1537,7 +1537,7 @@ impl<'a> Parser<'a> { // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds()?; impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; - TyKind::ImplTrait(bounds) + TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds) } else if self.check_keyword(keywords::Dyn) && self.look_ahead(1, |t| t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t)) { -- cgit 1.4.1-3-g733a5 From 9eb75613f0425743933612b59e65d22596af5165 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 26 Jun 2018 11:56:24 +0200 Subject: Generate `DefId`s for the impl trait of `async` functions --- src/librustc/hir/lowering.rs | 71 ++++++++++++++++++++++------------- src/librustc/hir/map/def_collector.rs | 22 ++++++++--- src/librustc_resolve/lib.rs | 9 +++-- src/libsyntax/ast.rs | 7 +++- src/libsyntax/feature_gate.rs | 2 +- src/libsyntax/fold.rs | 31 ++++++++++----- src/libsyntax/parse/parser.rs | 16 +++++--- 7 files changed, 102 insertions(+), 56 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index b7260dded92..004121147d9 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -863,7 +863,7 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { ), 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 @@ impl<'a> LoweringContext<'a> { |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 @@ impl<'a> LoweringContext<'a> { // 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` in the + // make_ret_async: if `Some`, converts `-> T` into `-> impl Future` in the // return type. This is used for `async fn` declarations. fn lower_fn_decl( &mut self, decl: &FnDecl, fn_def_id: Option, impl_trait_return_allow: bool, - make_ret_async: bool, + make_ret_async: Option, ) -> P { let inputs = decl.inputs .iter() @@ -1890,9 +1890,9 @@ impl<'a> LoweringContext<'a> { }) .collect::>(); - 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 @@ impl<'a> LoweringContext<'a> { inputs: &[P], 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 @@ impl<'a> LoweringContext<'a> { }; 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 @@ impl<'a> LoweringContext<'a> { // 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 @@ impl<'a> LoweringContext<'a> { } }); + 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { } 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 @@ impl<'a> LoweringContext<'a> { }); 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 @@ impl<'a> LoweringContext<'a> { sig, impl_item_def_id, impl_trait_return_allow, - sig.header.asyncness.is_async(), + asyncness, ), body_id, ) @@ -3100,8 +3111,8 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { |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 @@ impl<'a> LoweringContext<'a> { sig: &MethodSig, fn_def_id: DefId, impl_trait_return_allow: bool, - is_async: bool, + is_async: Option, ) -> hir::MethodSig { hir::MethodSig { header: self.lower_fn_header(sig.header), @@ -3278,7 +3295,7 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { // 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { }) } 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; diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 4884d440757..47ebc973102 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -77,6 +77,7 @@ impl<'a> DefCollector<'a> { &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 @@ impl<'a> DefCollector<'a> { 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 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { 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 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { 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 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { // 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); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2052918747b..15985009843 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -777,8 +777,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { 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 @@ impl<'a> Resolver<'a> { // 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)); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ca07ac7988d..d38af6a6088 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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 diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c813ec1977b..2a21e4c0171 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1726,7 +1726,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "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(..) => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1035be3a159..d9d3febc4fe 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -100,6 +100,10 @@ pub trait Folder : Sized { 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) -> P { noop_fold_block(b, self) } @@ -669,6 +673,16 @@ pub fn noop_fold_interpolated(nt: token::Nonterminal, fld: &mut T) } } +pub fn noop_fold_asyncness(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(decl: P, fld: &mut T) -> P { 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(i: ImplItem, folder: &mut T) } pub fn noop_fold_fn_header(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(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(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)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8690918c805..4c86a64b099 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1299,7 +1299,10 @@ impl<'a> Parser<'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 @@ impl<'a> Parser<'a> { } 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 @@ impl<'a> Parser<'a> { 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; -- cgit 1.4.1-3-g733a5