diff options
| author | Maybe Waffle <waffle.lapkin@gmail.com> | 2022-06-02 20:15:05 +0400 |
|---|---|---|
| committer | Maybe Waffle <waffle.lapkin@gmail.com> | 2022-07-12 16:25:16 +0400 |
| commit | 40ae7b5b8e09da657b62bc849b8bcdf99a1cb210 (patch) | |
| tree | f2a08c2651b0cb786a37697ee7806b272c01bb1d /compiler/rustc_ast | |
| parent | fbdb07f4e7f4666085aec4b1ed2fd05817dc42cf (diff) | |
| download | rust-40ae7b5b8e09da657b62bc849b8bcdf99a1cb210.tar.gz rust-40ae7b5b8e09da657b62bc849b8bcdf99a1cb210.zip | |
Parse closure binders
This is first step in implementing RFC 3216. - Parse `for<'a>` before closures in ast - Error in lowering - Add `closure_lifetime_binder` feature
Diffstat (limited to 'compiler/rustc_ast')
| -rw-r--r-- | compiler/rustc_ast/src/ast.rs | 27 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/mut_visit.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/visit.rs | 25 |
3 files changed, 62 insertions, 8 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f705d004422..ac2328a5824 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1390,7 +1390,7 @@ pub enum ExprKind { /// A closure (e.g., `move |a, b, c| a + b + c`). /// /// The final span is the span of the argument block `|...|`. - Closure(CaptureBy, Async, Movability, P<FnDecl>, P<Expr>, Span), + Closure(ClosureBinder, CaptureBy, Async, Movability, P<FnDecl>, P<Expr>, Span), /// A block (`'label: { ... }`). Block(P<Block>, Option<Label>), /// An async block (`async move { ... }`). @@ -1518,6 +1518,31 @@ pub enum Movability { Movable, } +/// Closure lifetime binder, `for<'a, 'b>` in `for<'a, 'b> |_: &'a (), _: &'b ()|`. +#[derive(Clone, Encodable, Decodable, Debug)] +pub enum ClosureBinder { + /// The binder is not present, all closure lifetimes are inferred. + NotPresent, + /// The binder is present. + For { + /// Span of the whole `for<>` clause + /// + /// ```text + /// for<'a, 'b> |_: &'a (), _: &'b ()| { ... } + /// ^^^^^^^^^^^ -- this + /// ``` + span: Span, + + /// Lifetimes in the `for<>` closure + /// + /// ```text + /// for<'a, 'b> |_: &'a (), _: &'b ()| { ... } + /// ^^^^^^ -- this + /// ``` + generic_params: P<[GenericParam]>, + }, +} + /// Represents a macro invocation. The `path` indicates which macro /// is being invoked, and the `args` are arguments passed to it. #[derive(Clone, Encodable, Decodable, Debug)] diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 85bb5296486..d933ea2da9e 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -125,6 +125,10 @@ pub trait MutVisitor: Sized { noop_visit_asyncness(a, self); } + fn visit_closure_binder(&mut self, b: &mut ClosureBinder) { + noop_visit_closure_binder(b, self); + } + fn visit_block(&mut self, b: &mut P<Block>) { noop_visit_block(b, self); } @@ -825,6 +829,17 @@ pub fn visit_constness<T: MutVisitor>(constness: &mut Const, vis: &mut T) { } } +pub fn noop_visit_closure_binder<T: MutVisitor>(binder: &mut ClosureBinder, vis: &mut T) { + match binder { + ClosureBinder::NotPresent => {} + ClosureBinder::For { span: _, generic_params } => { + let mut vec = std::mem::take(generic_params).into_vec(); + vec.flat_map_in_place(|param| vis.flat_map_generic_param(param)); + *generic_params = P::from_vec(vec); + } + } +} + pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut Async, vis: &mut T) { match asyncness { Async::Yes { span: _, closure_id, return_impl_trait_id } => { @@ -1336,7 +1351,8 @@ pub fn noop_visit_expr<T: MutVisitor>( vis.visit_expr(expr); arms.flat_map_in_place(|arm| vis.flat_map_arm(arm)); } - ExprKind::Closure(_capture_by, asyncness, _movability, decl, body, span) => { + ExprKind::Closure(binder, _capture_by, asyncness, _movability, decl, body, span) => { + vis.visit_closure_binder(binder); vis.visit_asyncness(asyncness); vis.visit_fn_decl(decl); vis.visit_expr(body); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 2ce8590d771..327fc505e99 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -56,14 +56,14 @@ pub enum FnKind<'a> { Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>), /// E.g., `|x, y| body`. - Closure(&'a FnDecl, &'a Expr), + Closure(&'a ClosureBinder, &'a FnDecl, &'a Expr), } impl<'a> FnKind<'a> { pub fn header(&self) -> Option<&'a FnHeader> { match *self { FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header), - FnKind::Closure(_, _) => None, + FnKind::Closure(_, _, _) => None, } } @@ -77,7 +77,7 @@ impl<'a> FnKind<'a> { pub fn decl(&self) -> &'a FnDecl { match self { FnKind::Fn(_, _, sig, _, _, _) => &sig.decl, - FnKind::Closure(decl, _) => decl, + FnKind::Closure(_, decl, _) => decl, } } @@ -155,6 +155,9 @@ pub trait Visitor<'ast>: Sized { fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) } + fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) { + walk_closure_binder(self, b) + } fn visit_where_predicate(&mut self, p: &'ast WherePredicate) { walk_where_predicate(self, p) } @@ -636,6 +639,15 @@ pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates); } +pub fn walk_closure_binder<'a, V: Visitor<'a>>(visitor: &mut V, binder: &'a ClosureBinder) { + match binder { + ClosureBinder::NotPresent => {} + ClosureBinder::For { span: _, generic_params } => { + walk_list!(visitor, visit_generic_param, generic_params) + } + } +} + pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) { match *predicate { WherePredicate::BoundPredicate(WhereBoundPredicate { @@ -682,7 +694,8 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Spa walk_fn_decl(visitor, &sig.decl); walk_list!(visitor, visit_block, body); } - FnKind::Closure(decl, body) => { + FnKind::Closure(binder, decl, body) => { + visitor.visit_closure_binder(binder); walk_fn_decl(visitor, decl); visitor.visit_expr(body); } @@ -856,8 +869,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr(subexpression); walk_list!(visitor, visit_arm, arms); } - ExprKind::Closure(_, _, _, ref decl, ref body, _decl_span) => { - visitor.visit_fn(FnKind::Closure(decl, body), expression.span, expression.id) + ExprKind::Closure(ref binder, _, _, _, ref decl, ref body, _decl_span) => { + visitor.visit_fn(FnKind::Closure(binder, decl, body), expression.span, expression.id) } ExprKind::Block(ref block, ref opt_label) => { walk_list!(visitor, visit_label, opt_label); |
