about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2017-10-07 16:36:28 +0200
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-01-23 05:10:38 +0100
commitccf0d8399e1ef3ed6bf7005650ce42aa646b5cc7 (patch)
tree78166bd01ee1a24b9251e6cdf16dd631d3cf65e1 /src/libsyntax
parent47a8eb7c4e24b61a8a9ab4eaff60ef65291aaa56 (diff)
downloadrust-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.rs9
-rw-r--r--src/libsyntax/ext/build.rs7
-rw-r--r--src/libsyntax/fold.rs3
-rw-r--r--src/libsyntax/parse/parser.rs45
-rw-r--r--src/libsyntax/print/pprust.rs11
-rw-r--r--src/libsyntax/visit.rs2
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,