From 4e5666eace14651539ca2a1f5eed8cdf0ccfb130 Mon Sep 17 00:00:00 2001 From: Brian Koropoff Date: Wed, 1 Oct 2014 22:24:10 -0700 Subject: [PATCH] Fix missing entries in upvar borrows map for capture-by-ref unboxed closures This prevents a later ICE in borrowck. Closes issue #17655 --- src/librustc/middle/typeck/check/regionck.rs | 42 ++++++++++++-------- 1 file 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,