diff options
| author | John Kåre Alsaker <john.kare.alsaker@gmail.com> | 2017-10-07 16:36:28 +0200 |
|---|---|---|
| committer | John Kåre Alsaker <john.kare.alsaker@gmail.com> | 2018-01-23 05:10:38 +0100 |
| commit | ccf0d8399e1ef3ed6bf7005650ce42aa646b5cc7 (patch) | |
| tree | 78166bd01ee1a24b9251e6cdf16dd631d3cf65e1 /src/libsyntax | |
| parent | 47a8eb7c4e24b61a8a9ab4eaff60ef65291aaa56 (diff) | |
| download | rust-ccf0d8399e1ef3ed6bf7005650ce42aa646b5cc7.tar.gz rust-ccf0d8399e1ef3ed6bf7005650ce42aa646b5cc7.zip | |
Adds support for immovable generators. Move checking of invalid borrows across suspension points to borrowck. Fixes #44197, #45259 and #45093.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 45 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 2 |
6 files changed, 62 insertions, 15 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a64f1e9e400..d6e26057ea8 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1100,7 +1100,7 @@ pub enum ExprKind { /// A closure (for example, `move |a, b, c| a + b + c`) /// /// The final span is the span of the argument block `|...|` - Closure(CaptureBy, P<FnDecl>, P<Expr>, Span), + Closure(CaptureBy, Movability, P<FnDecl>, P<Expr>, Span), /// A block (`{ ... }`) Block(P<Block>), /// A catch block (`catch { ... }`) @@ -1194,6 +1194,13 @@ pub enum CaptureBy { Ref, } +/// The movability of a generator / closure literal +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +pub enum Movability { + Static, + Movable, +} + pub type Mac = Spanned<Mac_>; /// Represents a macro invocation. The Path indicates which macro diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 7f7ff56fd7f..cf63592c2ec 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -912,6 +912,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn_decl_span: Span) // span of the `|...|` part -> P<ast::Expr> { self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, + ast::Movability::Movable, fn_decl, body, fn_decl_span)) @@ -930,7 +931,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> { // part of the lambda, but it probably (maybe?) corresponds to // the entire lambda body. Probably we should extend the API // here, but that's not entirely clear. - self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, body, span)) + self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, + ast::Movability::Movable, + fn_decl, + body, + span)) } fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr> { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c304e3a9f50..1e605ba3ecd 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1235,8 +1235,9 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::Match(folder.fold_expr(expr), arms.move_map(|x| folder.fold_arm(x))) } - ExprKind::Closure(capture_clause, decl, body, span) => { + ExprKind::Closure(capture_clause, movability, decl, body, span) => { ExprKind::Closure(capture_clause, + movability, folder.fold_fn_decl(decl), folder.fold_expr(body), folder.new_span(span)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3d58104260f..8213d604b91 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -14,7 +14,7 @@ use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Unsafety; use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind}; use ast::Block; -use ast::{BlockCheckMode, CaptureBy}; +use ast::{BlockCheckMode, CaptureBy, Movability}; use ast::{Constness, Crate}; use ast::Defaultness; use ast::EnumDef; @@ -2258,8 +2258,7 @@ impl<'a> Parser<'a> { return self.parse_block_expr(lo, BlockCheckMode::Default, attrs); } token::BinOp(token::Or) | token::OrOr => { - let lo = self.span; - return self.parse_lambda_expr(lo, CaptureBy::Ref, attrs); + return self.parse_lambda_expr(attrs); } token::OpenDelim(token::Bracket) => { self.bump(); @@ -2304,9 +2303,8 @@ impl<'a> Parser<'a> { hi = path.span; return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs)); } - if self.eat_keyword(keywords::Move) { - let lo = self.prev_span; - return self.parse_lambda_expr(lo, CaptureBy::Value, attrs); + if self.check_keyword(keywords::Move) || self.check_keyword(keywords::Static) { + return self.parse_lambda_expr(attrs); } if self.eat_keyword(keywords::If) { return self.parse_if_expr(attrs); @@ -3247,11 +3245,20 @@ impl<'a> Parser<'a> { // `move |args| expr` pub fn parse_lambda_expr(&mut self, - lo: Span, - capture_clause: CaptureBy, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { + let lo = self.span; + let movability = if self.eat_keyword(keywords::Static) { + Movability::Static + } else { + Movability::Movable + }; + let capture_clause = if self.eat_keyword(keywords::Move) { + CaptureBy::Value + } else { + CaptureBy::Ref + }; let decl = self.parse_fn_block_decl()?; let decl_hi = self.prev_span; let body = match decl.output { @@ -3269,7 +3276,7 @@ impl<'a> Parser<'a> { Ok(self.mk_expr( lo.to(body.span), - ExprKind::Closure(capture_clause, decl, body, lo.to(decl_hi)), + ExprKind::Closure(capture_clause, movability, decl, body, lo.to(decl_hi)), attrs)) } @@ -6271,6 +6278,23 @@ impl<'a> Parser<'a> { } } + fn is_static_global(&mut self) -> bool { + if self.check_keyword(keywords::Static) { + // Check if this could be a closure + !self.look_ahead(1, |token| { + if token.is_keyword(keywords::Move) { + return true; + } + match *token { + token::BinOp(token::Or) | token::OrOr => true, + _ => false, + } + }) + } else { + false + } + } + /// Parse one of the items allowed by the flags. /// NB: this function no longer parses the items inside an /// extern crate. @@ -6329,7 +6353,8 @@ impl<'a> Parser<'a> { self.unexpected()?; } - if self.eat_keyword(keywords::Static) { + if self.is_static_global() { + self.bump(); // STATIC ITEM let m = if self.eat_keyword(keywords::Mut) { Mutability::Mutable diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ff065b57b8d..345c592a011 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2162,7 +2162,8 @@ impl<'a> State<'a> { } self.bclose_(expr.span, INDENT_UNIT)?; } - ast::ExprKind::Closure(capture_clause, ref decl, ref body, _) => { + ast::ExprKind::Closure(capture_clause, movability, ref decl, ref body, _) => { + self.print_movability(movability)?; self.print_capture_clause(capture_clause)?; self.print_fn_block_args(decl)?; @@ -2777,6 +2778,14 @@ impl<'a> State<'a> { } } + pub fn print_movability(&mut self, movability: ast::Movability) + -> io::Result<()> { + match movability { + ast::Movability::Static => self.word_space("static"), + ast::Movability::Movable => Ok(()), + } + } + pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) -> io::Result<()> { match capture_clause { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index b5fc9236ad3..8aeacf79cee 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -739,7 +739,7 @@ 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 function_declaration, ref body, _decl_span) => { + ExprKind::Closure(_, _, ref function_declaration, ref body, _decl_span) => { visitor.visit_fn(FnKind::Closure(body), function_declaration, expression.span, |
