about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Koropoff <bkoropoff@gmail.com>2014-10-01 22:24:10 -0700
committerBrian Koropoff <bkoropoff@gmail.com>2014-10-02 21:08:08 -0700
commit4e5666eace14651539ca2a1f5eed8cdf0ccfb130 (patch)
tree8474f371f54e52da8181f089f70f814e55da38bc /src
parenta70a0374e24c146e714b0beb4437e571a488be4f (diff)
downloadrust-4e5666eace14651539ca2a1f5eed8cdf0ccfb130.tar.gz
rust-4e5666eace14651539ca2a1f5eed8cdf0ccfb130.zip
Fix missing entries in upvar borrows map for capture-by-ref unboxed closures
This prevents a later ICE in borrowck.

Closes issue #17655
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs42
1 files changed, 26 insertions, 16 deletions
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 9e20028569b..3a14b90f789 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -844,7 +844,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
                     // has static lifetime.
                 } else {
                     // Variables being referenced must outlive closure.
-                    constrain_free_variables_in_stack_closure(
+                    constrain_free_variables_in_by_ref_closure(
                         rcx, bounds.region_bound, expr, freevars);
 
                     // Closure is stack allocated and hence cannot
@@ -856,20 +856,17 @@ fn check_expr_fn_block(rcx: &mut Rcx,
             });
         }
         ty::ty_unboxed_closure(_, region) => {
-            ty::with_freevars(tcx, expr.id, |freevars| {
-                // No free variables means that there is no environment and
-                // hence the closure has static lifetime. Otherwise, the
-                // closure must not outlive the variables it closes over
-                // by-reference.
-                //
-                // NDM -- this seems wrong, discuss with pcwalton, should
-                // be straightforward enough.
-                if !freevars.is_empty() {
-                    let bounds = ty::region_existential_bound(region);
-                    ensure_free_variable_types_outlive_closure_bound(
-                        rcx, bounds, expr, freevars);
-                }
-            })
+            let bounds = ty::region_existential_bound(region);
+            if tcx.capture_modes.borrow().get_copy(&expr.id) == ast::CaptureByRef {
+                ty::with_freevars(tcx, expr.id, |freevars| {
+                    if !freevars.is_empty() {
+                        // Variables being referenced must be constrained and registered
+                        // in the upvar borrow map
+                        constrain_free_variables_in_by_ref_closure(
+                            rcx, bounds.region_bound, expr, freevars);
+                    }
+                })
+            }
         }
         _ => { }
     }
@@ -884,6 +881,13 @@ fn check_expr_fn_block(rcx: &mut Rcx,
                 propagate_upupvar_borrow_kind(rcx, expr, freevars);
             })
         }
+        ty::ty_unboxed_closure(..) => {
+            if tcx.capture_modes.borrow().get_copy(&expr.id) == ast::CaptureByRef {
+                ty::with_freevars(tcx, expr.id, |freevars| {
+                    propagate_upupvar_borrow_kind(rcx, expr, freevars);
+                });
+            }
+        }
         _ => {}
     }
 
@@ -893,6 +897,12 @@ fn check_expr_fn_block(rcx: &mut Rcx,
                 ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars);
             })
         }
+        ty::ty_unboxed_closure(_, region) => {
+            ty::with_freevars(tcx, expr.id, |freevars| {
+                let bounds = ty::region_existential_bound(region);
+                ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars);
+            })
+        }
         _ => {}
     }
 
@@ -959,7 +969,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
         }
     }
 
-    fn constrain_free_variables_in_stack_closure(
+    fn constrain_free_variables_in_by_ref_closure(
         rcx: &mut Rcx,
         region_bound: ty::Region,
         expr: &ast::Expr,