about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-05-19 21:21:05 +0530
committerManish Goregaokar <manishsmail@gmail.com>2016-05-19 21:21:05 +0530
commite4f33d5ae789b6081b73a125d3a847cd5d43b5c8 (patch)
treefa186c7c5138d0ed015741b69791a1b95f5bb60c
parentc9ca735a7b34cbe38e8ccc58d89d7a49c5b68ee2 (diff)
parent64feba03d76641a8eb290f3f8409d6be04b3fe11 (diff)
downloadrust-e4f33d5ae789b6081b73a125d3a847cd5d43b5c8.tar.gz
rust-e4f33d5ae789b6081b73a125d3a847cd5d43b5c8.zip
Rollup merge of #33611 - vvanders:master, r=steveklabnik
Add a note about Higher-Ranked Trait Bounds in docs on Closures.

I hit a snag with lifetimes a few days ago and it wasn't until @birkenfeld pointed out Higher-Ranked Trait Bounds that I was able to solve the issue involving lifetimes on closure traits. This adds a small section in the book so that other users can find it.

r? @steveklabnik
-rw-r--r--src/doc/book/closures.md47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md
index d81619b647f..e690f4edd47 100644
--- a/src/doc/book/closures.md
+++ b/src/doc/book/closures.md
@@ -319,6 +319,53 @@ assert_eq!(3, answer);
 Now we take a trait object, a `&Fn`. And we have to make a reference
 to our closure when we pass it to `call_with_one`, so we use `&||`.
 
+A quick note about closures that use explicit lifetimes. Sometimes you might have a closure
+that takes a reference like so:
+
+```
+fn call_with_ref<F>(some_closure:F) -> i32
+    where F: Fn(&i32) -> i32 {
+
+    let mut value = 0;
+    some_closure(&value)
+}
+```
+
+Normally you can specify the lifetime of the parameter to our closure. We
+could annotate it on the function declaration:
+
+```ignore
+fn call_with_ref<'a, F>(some_closure:F) -> i32 
+    where F: Fn(&'a 32) -> i32 {
+```
+
+However this presents a problem with in our case. When you specify the explict
+lifetime on a function it binds that lifetime to the *entire* scope of the function
+instead of just the invocation scope of our closure. This means that the borrow checker
+will see a mutable reference in the same lifetime as our immutable reference and fail
+to compile.
+
+In order to say that we only need the lifetime to be valid for the invocation scope
+of the closure we can use Higher-Ranked Trait Bounds with the `for<...>` syntax:
+
+```ignore
+fn call_with_ref<F>(some_closure:F) -> i32
+    where F: for<'a> Fn(&'a 32) -> i32 {
+```
+
+This lets the Rust compiler find the minimum lifetime to invoke our closure and 
+satisfy the borrow checker's rules. Our function then compiles and excutes as we
+expect.
+
+```
+fn call_with_ref<F>(some_closure:F) -> i32
+    where F: for<'a> Fn(&'a i32) -> i32 {
+
+    let mut value = 0;
+    some_closure(&value)
+}
+```
+
 # Function pointers and closures
 
 A function pointer is kind of like a closure that has no environment. As such,