about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-09-13 08:06:00 +0000
committerbors <bors@rust-lang.org>2014-09-13 08:06:00 +0000
commit90304ed2669a9554a5aa5c58194e71fa373abe13 (patch)
tree572c4c7259015d9320162fd3b74b51cd4f8cc73c
parenta9cf19889ae7030c7df25cf41105906d12616f1e (diff)
parenta9b929dbb6b8e86ccedf96a207a6253c0af1d6c9 (diff)
auto merge of #17175 : pcwalton/rust/region-bounds-on-closures, r=huonw
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]

r? @huonw
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs4
-rw-r--r--src/test/compile-fail/region-bound-on-closure-outlives-call.rs16
2 files changed, 20 insertions, 0 deletions
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 8cd8a6aa051..843d6a582ea 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() {}
+