Closure as function parameter "cannot infer an appropriate lifetime due to conflicting requirements" - closures

I am trying to use a closure as function parameter:
fn foo(f: Box<Fn() -> bool>) -> bool {
f()
}
fn main() {
let bar = 42;
foo(Box::new(|| bar != 42));
}
but I get this lifetime error:
src/main.rs:7:24: 7:36 error: cannot infer an appropriate lifetime due to conflicting requirements
src/main.rs:7 let n = foo(Box::new(|| bar != 42));
^~~~~~~~~~~~
src/main.rs:7:15: 7:23 note: first, the lifetime cannot outlive the expression at 7:14...
src/main.rs:7 let n = foo(Box::new(|| bar != 42));
^~~~~~~~
src/main.rs:7:15: 7:23 note: ...so that the type `[closure src/main.rs:7:24: 7:36]` will meet its required lifetime bounds
src/main.rs:7 let n = foo(Box::new(|| bar != 42));
^~~~~~~~
src/main.rs:7:15: 7:37 note: but, the lifetime must be valid for the call at 7:14...
src/main.rs:7 let n = foo(Box::new(|| bar != 42));
^~~~~~~~~~~~~~~~~~~~~~
src/main.rs:7:24: 7:36 note: ...so that argument is valid for the call
src/main.rs:7 let n = foo(Box::new(|| bar != 42));
^~~~~~~~~~~~
error: aborting due to previous error
I don't understand why the lifetime is not properly infered. What can I do to fix that ?
$ rustc --version
rustc 1.0.0-nightly (6c065fc8c 2015-02-17) (built 2015-02-18)

if you want to use a boxed closure you need to use move || {}.
fn foo(f: Box<Fn() -> bool>)
-> bool {
f()
}
fn main() {
let bar = 42;
let blub = foo(Box::new(move || bar != 42));
}
On the other hand, you cannot use an unboxed closure directly, as it may contain any number of captured elements, and is therefor unsized. By using generics you can easily circumvent this limitation:
fn foo<T>(f: T)
-> bool
where T : Fn() -> bool {
f()
}
fn main() {
let bar = 42;
let blub = foo(|| bar != 42);
}

Related

Passing a closure that modifies its environment to a function in Rust

I have a closure that captures and modifies its environment. I want to pass this closure to a function that accepts closures:
fn main() {
let mut integer = 5;
let mut closure_variable = || -> i32 {
integer += 1;
integer
};
execute_closure(&mut closure_variable);
}
fn execute_closure(closure_argument: &mut Fn() -> i32) {
let result = closure_argument();
println!("Result of closure: {}", result);
}
Because the closure modifies its environment, this fails:
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
--> src/main.rs:3:32
|
3 | let mut closure_variable = || -> i32 {
| ________________________________^
4 | | integer += 1;
5 | | integer
6 | | };
| |_____^
7 | execute_closure(&mut closure_variable);
| --------------------- the requirement to implement `Fn` derives from here
|
note: closure is `FnMut` because it mutates the variable `integer` here
--> src/main.rs:4:9
|
4 | integer += 1;
| ^^^^^^^
As I understand from When does a closure implement Fn, FnMut and FnOnce?, this means that my closure actually is expanded to a struct that implements the trait FnMut. This trait is mutable, meaning calling the function changes the (implicit) object. I think this correct, because the variable integer should be modified after calling execute_closure().
How do I convince the compiler this is okay and that I actually want to call a FnMut function? Or is there something fundamentally wrong with how I use Rust in this example?
If you can change the function that accepts the closure...
Accept a FnMut instead of a Fn:
fn main() {
let mut integer = 5;
execute_closure(|| {
integer += 1;
integer
});
}
fn execute_closure<F>(mut closure_argument: F)
where
F: FnMut() -> i32,
{
let result = closure_argument();
println!("Result of closure: {}", result);
}
If you can not change the function that accepts the closure...
Use interior mutability provided by types like Cell or RefCell:
use std::cell::Cell;
fn main() {
let integer = Cell::new(5);
execute_closure(|| {
integer.set(integer.get() + 1);
integer.get()
});
}
fn execute_closure<F>(closure_argument: F)
where
F: Fn() -> i32,
{
let result = closure_argument();
println!("Result of closure: {}", result);
}
Or is there something fundamentally wrong with how I use Rust in this example?
Perhaps. An argument of type &mut Fn() -> i32 cannot mutate the variables it has closed over, so the error message makes sense to me.
It's kind of similar to the type &mut &u8 — you could alter the outer reference to point to another immutable reference, but you cannot "ignore" the inner immutability and change the numeric value.
Aside:
The original code uses dynamic dispatch because there is a trait object that provides indirection. In many cases you'd see this version that I posted above, which uses static dispatch and can be monomorphized. I've also inlined the closure as that's the normal syntax.
Here's the original version with just enough changes to work:
fn main() {
let mut integer = 5;
let mut closure_variable = || -> i32 {
integer += 1;
integer
};
execute_closure(&mut closure_variable);
}
fn execute_closure(closure_argument: &mut FnMut() -> i32) {
let result = closure_argument();
println!("Result of closure: {}", result);
}

How do I capture variables outside the scope of a closure in Rust?

I'm writing a case-insensitive anagram finder given a word and a list of words. I have the following code:
pub fn anagrams_for(s: &'static str, v: &[&'static str]) -> Vec<&'static str> {
let mut s_sorted: Vec<_> = s.to_lowercase().chars().collect();
s_sorted.sort();
v.iter().filter_map(move |word: &str| {
let mut word_sorted: Vec<_> = word.to_lowercase().chars().collect();
word_sorted.sort();
if word_sorted == s_sorted && s.to_lowercase() != word.to_lowercase() {
Some(word)
} else {
None
}
}).collect()
}
The logic of this is to sort the lowercase given word, and for each word in the vector, do the same. If the words are different pre-sort (to eliminate self-anagrams) but are the same post-sort, add it to the output.
The above seems to have problems capturing s and s_sorted from the surrounding scope, though, because when I compile I get the following error:
error: type mismatch: the type [closure#src/lib.rs:23:25: 32:6 s_sorted:_, s:_] implements the trait for<'r> core::ops::FnMut<(&'r str,)>, but the trait core::ops::FnMut<(&&str,)> is required (expected &-ptr, found str)
When I looked at the description of this error type ([E0281]), I found the following TL;DR:
The issue in this case is that foo is defined as accepting a Fn with no
arguments, but the closure we attempted to pass to it requires one argument.
This is confusing because I thought move closures capture variables from the surrounding scope.
What am I missing?
This doesn't have anything to do with capturing variables in the closure. Let's check out the error message again, reformatted a bit:
type mismatch:
the type `[closure#<anon>:5:25: 14:6 s_sorted:_, s:_]`
implements the trait `for<'r> core::ops::FnMut<(&'r str,)>`,
but the trait `core::ops::FnMut<(&&str,)>` is required
(expected &-ptr, found str)
And more clearly:
found: for<'r> core::ops::FnMut<(&'r str,)>
expected: core::ops::FnMut<(&&str,)>
And zooming in even further:
found: &'r str
expected: &&str
The culprit is this: |word: &str|.
You have declared that your closure accepts a string slice, but that's not what the iterator yields. v is a slice of &str, and an iterator over a slice returns references to the items in the slice. Each iterator element is a &&str.
Change your closure to |&word| and it will work. This uses pattern matching to dereference the closure argument once before the value is bound to word. Equivalently (but less idiomatically), you could use |word| and then *word inside the closure.
Additionally...
You don't need to restrict yourself to 'static strings:
pub fn anagrams_for<'a>(s: &str, v: &[&'a str]) -> Vec<&'a str> {
It doesn't need to be a move closure.
Extract the logic of creating the vector of sorted chars. This helps ensure that the logic stays consistent between the two and means you don't have to declare those vectors as mutable for longer than needed.
fn sorted_chars(s: &str) -> Vec<char> {
let mut s_sorted: Vec<_> = s.to_lowercase().chars().collect();
s_sorted.sort();
s_sorted
}
pub fn anagrams_for<'a>(s: &str, v: &[&'a str]) -> Vec<&'a str> {
let s_sorted = sorted_chars(s);
v.iter().filter_map(|&word| {
let word_sorted = sorted_chars(word);
if word_sorted == s_sorted && s.to_lowercase() != word.to_lowercase() {
Some(word)
} else {
None
}
}).collect()
}
fn main() {}
The issue here is that you are attempting to create a Vec<&'static str> from a sequence of &&'static str.
pub fn anagrams_for(s: &'static str, v: &[&'static str]) -> Vec<&'static str> {
let mut s_sorted: Vec<_> = s.to_lowercase().chars().collect();
s_sorted.sort();
v.iter().cloned().filter_map(|word: &'static str| {
let mut word_sorted: Vec<_> = word.to_lowercase().chars().collect();
word_sorted.sort();
if word_sorted == s_sorted && s.to_lowercase() != word.to_lowercase() {
Some(word)
} else {
None
}
}).collect()
}
The cloned call is necessary to go from a &&'static str to a &'static str. This is an inexpensive operation since a &str is just a pointer to some utf8 sequence, plus a length.
Edit: actually an even better solution is to clone as late as possible
v.iter().filter_map(move |word: &&'static str| { // <--- adapted the type to what is actually received
let mut word_sorted: Vec<_> = word.to_lowercase().chars().collect();
word_sorted.sort();
if word_sorted == s_sorted && s.to_lowercase() != word.to_lowercase() {
Some(word.clone()) // <--- moved clone operation here
} else {
None
}
}).collect()

Conflicting lifetime requirements when storing closure capturing returned value

EDIT:
I'm trying to create a vector of closures inside a function, add a standard closure to the vector, and then return the vector from the function. I'm getting an error about conflicting lifetimes.
Code can be executed here.
fn vec_with_closure<'a, T>(f: Box<FnMut(T) + 'a>) -> Vec<Box<FnMut(T) + 'a>>
{
let mut v = Vec::<Box<FnMut(T)>>::new();
v.push(Box::new(|&mut: t: T| {
f(t);
}));
v
}
fn main() {
let v = vec_with_closure(Box::new(|t: usize| {
println!("{}", t);
}));
for c in v.iter_mut() {
c(10);
}
}
EDIT 2:
Using Rc<RefCell<...>> together with move || and the Fn() trait as opposed to the FnMut()m as suggested by Shepmaster, helped me produce a working version of the above code. Rust playpen version here.
Here's my understanding of the problem, slightly slimmed down:
fn filter<F>(&mut self, f: F) -> Keeper
where F: Fn() -> bool + 'static //'
{
let mut k = Keeper::new();
self.subscribe(|| {
if f() { k.publish() }
});
k
}
In this method, f is a value that has been passed in by-value, which means that filter owns it. Then, we create another closure that captures f by-reference. We are then trying to save that closure somewhere, so all the references in the closure need to outlive the lifetime of our struct (I picked 'static for convenience).
However, f only lives until the end of the method, so it definitely won't live long enough. We need to make the closure own f. It would be ideal if we could use the move keyword, but that causes the closure to also move in k, so we wouldn't be able to return it from the function.
Trying to solve that led to this version:
fn filter<F>(&mut self, f: F) -> Keeper
where F: Fn() -> bool + 'static //'
{
let mut k = Keeper::new();
let k2 = &mut k;
self.subscribe(move || {
if f() { k2.publish() }
});
k
}
which has a useful error message:
error: `k` does not live long enough
let k2 = &mut k;
^
note: reference must be valid for the static lifetime...
...but borrowed value is only valid for the block
Which leads to another problem: you are trying to keep a reference to k in the closure, but that reference will become invalid as soon as k is returned from the function. When items are moved by-value, their address will change, so references are no longer valid.
One potential solution is to use Rc and RefCell:
fn filter<F>(&mut self, f: F) -> Rc<RefCell<Keeper>>
where F: Fn() -> bool + 'static //'
{
let mut k = Rc::new(RefCell::new(Keeper::new()));
let k2 = k.clone();
self.subscribe(move || {
if f() { k2.borrow_mut().publish() }
});
k
}

Type aliases for closures

I would've thought the following code would work:
use std::num::{Num};
use std::fmt::{Show};
pub type GradFn<T : Num> = for<'a> fn(&'a [T]) -> (T, Vec<T>);
fn minimize<T : Show, F>(f : GradFn<T>, x0 : &[T]) {
// some no-op to test types
print!("{}",f(x0))
}
fn main() {
let xSquared : GradFn<f64> = |x : &[f64]| -> (f64, Vec<f64>) {
return (x[0] * x[0], vec![2.0 * x[0]]);
};
let (fx, grad) = xSquared(vec![2.0f64].as_slice());
print!("{}", fx);
}
But I'm getting a compiler error (see here):
<anon>:12:32: 14:4 error: mismatched types: expected `fn(&'a [f64]) -> (f64, collections::vec::Vec<f64>)`, found `|&[f64]| -> (f64, collections::vec::Vec<f64>)` (expected extern fn, found fn)
<anon>:12 let xSquared : GradFn<f64> = |x : &[f64]| -> (f64, Vec<f64>) {
<anon>:13 return (x[0] * x[0], vec![2.0 * x[0]]);
<anon>:14 };
fn does not define a closure type; it defines bare function pointers (i.e. pointers to functions defined with the fn keyword). That's why you can't assign a closure to a GradFn. Instead, you want to use either Fn, FnMut or FnOnce.
There are a few more changes I needed to make to get this code to compile:
On minimize, the f parameter as you wrote it receives an unsized type by value, which is forbidden. You also put an F type parameter that you don't use. You probably meant to constrain F and to use F as the type of f.
The compiler won't let us use a type alias in a type parameter constraint; we need to spell out the trait fully. This means the type alias is basically useless.
I removed the type annotation on xSquared, which is unnecessary. This let me remove the type alias completely.
Here's the final code:
#![feature(unboxed_closures)]
use std::num::{Num};
use std::fmt::{Show};
fn minimize<T: Show, F: FnMut(&[T]) -> (T, Vec<T>)>(mut f: F, x0: &[T]) {
// some no-op to test types
print!("{}", f(x0))
}
fn main() {
let xSquared = |x: &[f64]| -> (f64, Vec<f64>) {
return (x[0] * x[0], vec![2.0 * x[0]]);
};
let (fx, grad) = xSquared(vec![2.0f64].as_slice());
print!("{}", fx);
}
If your GradFn is actually going to be a bare function pointer (as opposed to a closure) you can keep the type alias, like this:
use std::num::Num;
use std::fmt::Show;
// this type has to point to a bare function, not a closure
pub type GradFn<T> = for<'a> fn(&'a [T]) -> (T, Vec<T>);
fn minimize<T>(f : GradFn<T>, x0 : &[T])
where T: Show + Num {
// some no-op to test types
println!("{}",f(x0))
}
fn main() {
// this is now a bare function
fn x_squared(x : &[f64]) -> (f64, Vec<f64>) {
return (x[0] * x[0], vec![2.0 * x[0]]);
}
// and this is a pointer to it, that uses your type alias
let x_sq : GradFn<f64> = x_squared;
let (fx, grad) = x_sq(&[2f64]);
println!("fx: {} - grad: {}", fx, grad);
minimize(x_sq, &[3f64]);; // works with minimize as well
}

Am I abusing the inline modifier?

I've been working on polishing up my JSON code for my ECMAScript runtime and I decided to run an experiment. The following str function has 4 logical steps which I've broken up into functions and marked them inline.
and private str (state:StringifyState) (key:string) (holder:IObject) : IDynamic =
let inline fourth (value:IDynamic) =
match value.TypeCode with
| LanguageTypeCode.Null ->
state.environment.CreateString "null" :> IDynamic
| LanguageTypeCode.Boolean ->
let v = value :?> IBoolean
state.environment.CreateString (if v.BaseValue then "true" else "false") :> IDynamic
| LanguageTypeCode.String ->
let v = value :?> IString
state.environment.CreateString (quote v.BaseValue) :> IDynamic
| LanguageTypeCode.Number ->
let v = value :?> INumber
if not (Double.IsInfinity(v.BaseValue))
then v.ConvertToString() :> IDynamic
else state.environment.CreateString "null" :> IDynamic
| LanguageTypeCode.Object ->
let v = value :?> IObject
let v = if v.Class = "Array" then ja state v else jo state v
state.environment.CreateString v :> IDynamic
| _ ->
state.environment.Undefined :> IDynamic
let inline third (value:IDynamic) =
match value.TypeCode with
| LanguageTypeCode.Object ->
let v = value :?> IObject
match v.Class with
| "Number" ->
fourth (v.ConvertToNumber())
| "String" ->
fourth (v.ConvertToString())
| "Boolean" ->
fourth (v.ConvertToBoolean())
| _ ->
fourth value
| _ ->
fourth value
let inline second (value:IDynamic) =
match state.replacerFunction with
| :? ICallable as f ->
let args = state.environment.CreateArgs ([| state.environment.CreateString key :> IDynamic; value |])
let value = f.Call (state.environment, holder :> IDynamic, args)
third value
| _ ->
third value
let inline first (value:IDynamic) =
match value with
| :? IObject as v ->
let toJSON = v.Get "toJSON"
match toJSON with
| :? ICallable as f ->
let args = state.environment.CreateArgs ([| state.environment.CreateString key :> IDynamic |])
let value = f.Call (state.environment, value, args)
second value
| _ ->
second value
| _ ->
second value
first (holder.Get key)
I compiled with full optimizations and opened up the resulting assembly with Reflector to see the results.
[CompilationArgumentCounts(new int[] { 1, 1, 1 })]
internal static IDynamic str(StringifyState state, string key, IObject holder)
{
IObject obj3;
ICallable callable;
ICallable callable2;
IArgs args;
IDynamic dynamic3;
IDynamic dynamic4;
ICallable callable3;
IDynamic dynamic5;
IBoolean flag;
IString str;
INumber number;
IObject obj4;
string str2;
INumber number2;
IObject obj5;
string str3;
IString str4;
IBoolean flag2;
IDynamic thisBinding = holder.Get(key);
IObject obj2 = thisBinding as IObject;
if (obj2 == null)
{
callable = state.replacerFunction# as ICallable;
if (callable == null)
{
switch (thisBinding.TypeCode)
{
case LanguageTypeCode.Object:
obj3 = (IObject) thisBinding;
str2 = obj3.Class;
if (!string.Equals(str2, "Number"))
{
if (string.Equals(str2, "String"))
{
dynamic3 = obj3.ConvertToString();
switch (dynamic3.TypeCode)
{
case LanguageTypeCode.Null:
return (IDynamic) state.environment#.CreateString("null");
case LanguageTypeCode.Boolean:
flag = (IBoolean) dynamic3;
return (IDynamic) state.environment#.CreateString(!flag.BaseValue ? "false" : "true");
case LanguageTypeCode.String:
str4 = (IString) dynamic3;
return (IDynamic) state.environment#.CreateString(quote(str4.BaseValue));
case LanguageTypeCode.Number:
number = (INumber) dynamic3;
if (double.IsInfinity(number.BaseValue))
{
return (IDynamic) state.environment#.CreateString("null");
}
return (IDynamic) number.ConvertToString();
// ... I removed a large amount of code.
return (IDynamic) state.environment#.Undefined;
}
Clearly the inline modifier is quite literal. The code is quite huge and with some preliminary tests is very efficient. One might consider throwing inline on all of their functions if they didn't care about the size of the resulting assemblies. What are some guidelines I can follow to know when the use of inline is appropriate? If possible I would like to avoid having to measure performance every single time to determine this.
If you are using inline solely for performance considerations, then I think that all of the typical performance-related advice applies. Most importantly, set a performance target and profile your application for hotspots. Then use inline if you have reason to believe that it will improve performance, and test to verify that it does. Keep in mind that the IL that the F# compiler generates is JIT compiled anyway, so small functions (in terms of IL size) may be inlined in the compilation to machine code even if you don't use inline in your F# code.
I typically only use inline when I want to use statically resolved type variables (e.g. because of member constraints).
I agree with kvb's answer, but here are two specific reasons not to
consider throwing inline on all of their functions if they didn't care about the size of the resulting assemblies.
The obvious case is that inlining anonymous functions won't work.
More inlining (especially of big functions) -> less (effectively) code fits into cache -> the program works slower.

Resources