From a9b929dbb6b8e86ccedf96a207a6253c0af1d6c9 Mon Sep 17 00:00:00 2001 From: Patrick Walton <pcwalton@mimiga.net> Date: Thu, 11 Sep 2014 11:59:05 -0700 Subject: [PATCH] librustc: Make sure region bounds on closures outlive calls to them. This can break code like: fn call_rec(f: |uint| -> uint) -> uint { (|x| f(x))(call_rec(f)) } Change this code to use a temporary instead of violating the borrow rules: fn call_rec(f: |uint| -> uint) -> uint { let tmp = call_rec(|x| f(x)); f(tmp) } Closes #17144. [breaking-change] --- src/librustc/middle/typeck/check/regionck.rs | 4 ++++ .../region-bound-on-closure-outlives-call.rs | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/compile-fail/region-bound-on-closure-outlives-call.rs diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index c08401375ca..6ddb10cc8ca 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -1064,6 +1064,10 @@ fn constrain_callee(rcx: &mut Rcx, }; rcx.fcx.mk_subr(infer::InvokeClosure(callee_expr.span), call_region, region); + + let region = closure_ty.bounds.region_bound; + rcx.fcx.mk_subr(infer::InvokeClosure(callee_expr.span), + call_region, region); } _ => { // this should not happen, but it does if the program is diff --git a/src/test/compile-fail/region-bound-on-closure-outlives-call.rs b/src/test/compile-fail/region-bound-on-closure-outlives-call.rs new file mode 100644 index 00000000000..13ab7acaf48 --- /dev/null +++ b/src/test/compile-fail/region-bound-on-closure-outlives-call.rs @@ -0,0 +1,16 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn call_rec(f: |uint| -> uint) -> uint { + (|x| f(x))(call_rec(f)) //~ ERROR cannot move out of `f` +} + +fn main() {} +