How to give a reference an explicit lifetime in rust? [duplicate] - memory

This question already has answers here:
Return local String as a slice (&str)
(7 answers)
Closed 8 months ago.
I'm trying to return a Result<(), &str> in rust, where the &str has embedded data about any errors which have occurred. For example, say I have the following code:
struct Foo {
pub mynum :i32,
}
impl Foo {
fn do_something(&self) -> Result<(), &str> {
if self.mynum % 12 == 0 {
return Err(&format!("error! mynum is {}", self.mynum))
}
Ok(())
}
}
fn main() {
let foo_instance = Foo{
mynum: 36,
};
let result = foo_instance.do_something().unwrap();
println!("{:?}",result)
}
If I run this in the rust playground, I get
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:9:20
|
9 | return Err(&format!("error! mynum is {}", self.mynum))
| ^^^^^-----------------------------------------^
| | |
| | temporary value created here
| returns a value referencing data owned by the current function
which isn't desired.
How do I tell the Rust compiler that to create a &str with lifetime 'a where 'a is the lifetime of self? I don't want to use 'static if possible, and I don't want to load Foo with extra members..

You should not return a &str in this case because the underlying object the &str is referencing gets dropped when the function terminates. Essentially, you are attempting to return a reference to a temporary value which gets deleted. See this article on differences between String and &str.
String is probably what you want instead. This compiles:
fn do_something(&self) -> Result<(), String> {
if self.mynum % 12 == 0 {
return Err(format!("error! mynum is {}", self.mynum));
}
Ok(())
}

Related

Are dependency injection containers that return references to values allocated in a local function fundamentally impossible in Rust?

In my mind one of the ideal traits for a dependency injection container would look like:
pub trait ResolveOwn<T> {
fn resolve(&self) -> T;
}
I don't know how to implement this for certain T. I keep stubbing my toes on variations and cousins of this error:
error[E0515]: cannot return value referencing local variable `X`
I'm used to dependency injection in C# where returning values referencing local variables is precisely how you implement the equivalent of that resolve function.
Here's an illustration that focuses on this aspect of dependency injection:
struct ComplexThing<'a>(&'a i32);
struct Module();
impl Module {
fn resolve_foo(&self) -> i32 {
todo!()
}
pub fn resolve_complex_thing_1(&self) -> ComplexThing {
let foo = self.resolve_foo();
ComplexThing(&foo)
}
}
error[E0515]: cannot return value referencing local variable `foo`
--> src/lib.rs:12:9
|
12 | ComplexThing(&foo)
| ^^^^^^^^^^^^^----^
| | |
| | `foo` is borrowed here
| returns a value referencing data owned by the current function
See? There's that error.
My first instinct (again, coming from C#) is to give the local variable a place to live in the returned value, because the local variable is created here but it needs to live at least as long as the returned value. Hmm... that sounds sort of like returning a closure. Let's see how that goes...
pub fn resolve_complex_thing_2<'a>(&'a self) -> impl FnOnce() -> ComplexThing<'a> {
let foo = self.resolve_foo();
move || ComplexThing(&foo)
}
error[E0515]: cannot return value referencing local data `foo`
--> src/lib.rs:12:17
|
12 | move || ComplexThing(&foo)
| ^^^^^^^^^^^^^----^
| | |
| | `foo` is borrowed here
| returns a value referencing data owned by the current function
No joy. It doesn't work to package this closure up into a prettier type (like some impl of Into<ComplexThing<'a>>) because it's fundamentally about returning a value referencing local data.
My next instinct is to somehow jam the local data into some kind of weak cache inside my Module and then get a reference from there (undoubtedly unsafely). And then the weak cache will need to solve half of the hard problems in Computer Science (hint: the other hard problem is naming things). That's starting to sound an awful lot like... oh no. Garbage collection!
I also thought about inverting the flow of control. It's hideous and still doesn't work:
impl Module {
pub fn use_foo<T>(&self, f: impl FnOnce(i32) -> T) -> T {
(f)(42)
}
pub fn use_complex_thing<'a, T>(&'a self, f: impl FnOnce(ComplexThing<'a>) -> T) -> T {
self.use_foo(
|foo| (f)(ComplexThing(&foo)),
)
}
}
error[E0597]: `foo` does not live long enough
--> src/lib.rs:12:36
|
10 | pub fn use_complex_thing<'a, T>(&'a self, f: impl FnOnce(ComplexThing<'a>) -> T) -> T {
| -- lifetime `'a` defined here
11 | self.use_foo(
12 | |foo| (f)(ComplexThing(&foo)),
| -----------------^^^^--
| | | |
| | | `foo` dropped here while still borrowed
| | borrowed value does not live long enough
| argument requires that `foo` is borrowed for `'a`
My last instinct is to hack around the restriction against moving a value with active borrows, because then I could trick the compiler. My attempts at implementing that resulted in a type that's impossible to use correctly — it ended up requiring knowledge that only the compiler has and seemed to introduce undefined behavior at every turn. I won't bother reproducing that code here.
It seems like it's impossible to return any owned instances of types containing (non-singleton) references.
Assuming that's true, that means there are entire classes of types that simply cannot be created with a dependency injection container in Rust.
Surely I'm missing something?
You can try making a drop guard along with Box::leak to leak a reference to live long enough, then have custom behavior on Drop to reclaim the leaked memory. Note that this will require you to do everything through the drop guard:
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
struct ComplexThing<'a>(&'a i32);
struct Module;
pub struct DropGuard<'a, T: 'a, V: 'a> {
// do NOT make these fields pub
// direct manipulation of these is very unsafe
container: ManuallyDrop<T>,
value: *mut V,
// I'm not sure this is needed but better safe than sorry
_value: PhantomData<&'a mut V>,
}
impl<'a, T: 'a, V: 'a> DropGuard<'a, T, V> {
pub fn new<F: FnOnce(&'a mut V) -> T>(value: Box<V>, gen: F) -> Self {
// leak the value so it lives long enough
let leaked = Box::leak(value);
// get a pointer to know what to drop
let leaked_ptr: *mut _ = leaked;
DropGuard {
container: ManuallyDrop::new(gen(leaked)),
value: leaked_ptr,
_value: PhantomData,
}
}
}
// so you can actually use it
// no DerefMut since dropping the container without dropping the guard is weird
impl<'a, T: 'a, V: 'a> std::ops::Deref for DropGuard<'a, T, V> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.container
}
}
impl<'a, T: 'a, V: 'a> Drop for DropGuard<'a, T, V> {
fn drop(&mut self) {
// drop the container first
// this should be safe since self.container is never referenced again
// the value its borrowing is still valid (due to not being dropped yet)
// and there should be no references to it (due to this struct being dropped)
unsafe {
ManuallyDrop::drop(&mut self.container);
}
// now drop the pointer
// this should be safe since it was created with Box::leak
// and the container borrowing it has already been dropped
// and no more references should have survived
std::mem::drop(unsafe { Box::from_raw(self.value) });
}
}
impl Module {
pub fn resolve_foo(&self) -> i32 {
5
}
pub fn resolve_complex_thing_1(&self) -> DropGuard<ComplexThing, i32> {
DropGuard::new(Box::new(self.resolve_foo()), |i32_ref| {
ComplexThing(i32_ref)
})
}
}
fn main() {
let module = Module;
let guard = module.resolve_complex_thing_1();
println!("{:?}", guard.0);
}
Playground link
Another way that also cleans up the typing is to use a trait:
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
struct ComplexThing<'a>(&'a i32);
struct Module;
// not sure if this trait should be unsafe
// but again, better safe than sorry
pub unsafe trait Guardable {
type Value;
}
unsafe impl Guardable for ComplexThing<'_> {
type Value = i32;
}
pub struct DropGuard<'a, T: 'a + Guardable> {
// do NOT make these fields pub
// direct manipulation of these is very unsafe
container: ManuallyDrop<T>,
value: *mut T::Value,
// I'm not sure this is needed but better safe than sorry
_value: PhantomData<&'a mut T::Value>,
}
impl<'a, T: 'a + Guardable> DropGuard<'a, T> {
pub fn new<F: FnOnce(&'a mut T::Value) -> T>(value: Box<T::Value>, gen: F) -> Self {
// leak the value so it lives long enough
let leaked = Box::leak(value);
// get a pointer to know what to drop
let leaked_ptr: *mut _ = leaked;
DropGuard {
container: ManuallyDrop::new(gen(leaked)),
value: leaked_ptr,
_value: PhantomData,
}
}
}
// so you can actually use it
// no DerefMut since dropping the container without dropping the guard is weird
impl<'a, T: 'a + Guardable> std::ops::Deref for DropGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.container
}
}
impl<'a, T: 'a + Guardable> Drop for DropGuard<'a, T> {
fn drop(&mut self) {
// drop the container first
// this should be safe since self.container is never referenced again
// the value its borrowing is still valid (due to not being dropped yet)
// and there should be no references to it (due to this struct being dropped)
unsafe {
ManuallyDrop::drop(&mut self.container);
}
// now drop the pointer
// this should be safe since it was created with Box::leak
// and the container borrowing it has already been dropped
// and no more references should have survived
std::mem::drop(unsafe { Box::from_raw(self.value) });
}
}
impl Module {
pub fn resolve_foo(&self) -> i32 {
5
}
pub fn resolve_complex_thing_1(&self) -> DropGuard<ComplexThing> {
DropGuard::new(Box::new(self.resolve_foo()), |i32_ref| {
ComplexThing(i32_ref)
})
}
}
fn main() {
let module = Module;
let guard = module.resolve_complex_thing_1();
println!("{:?}", guard.0);
}
Playground link
Since every container should only have one valid DropGuard value type, you can put that in an associated type in a trait, so now you can work with DropGuard<ComplexThing> instead of DropGuard<ComplexThing, i32>, and this also prevents you from having bogus values in the DropGuard.
Disclaimer: I'm fairly new to Rust; this answer is based on limited experience and may be un-nuanced.
As a general principle of Rust program design — not specific to dependency injection — you should plan not to use references except for things that are one of:
temporary, i.e. confined to the life of some stack frame (or technically longer than that in the case of async functions, but you get the idea, I hope)
compile-time constants or lazily initialized singletons, i.e. &'static references
The reason is that Rust does not — without various trickery — support lifetimes that are not one of those two cases.
Any structures which are needed for longer durations than that should be designed to not contain non-'static references — and instead use owned values. In other words, let your DI be like
pub trait ResolveOwn<T: 'static> {
// ^^^^^^^^^^
fn resolve(&self) -> T;
}
Don't actually add that lifetime constraint: it doesn't buy you anything, and might be inconvenient (for example, in a test that wants to inject things referring to the test — which will work fine since they live longer than the entire DI container — or if the application's actual main() has something to share, similarly). But plan as if it were there.
Given this constraint, how can you implement things that seem to want references?
In the simplest cases, just use owned values and don't worry about any extra cloning required unless it proves to be a performance issue.
Use Rc or Arc for reference-counted smart pointers that keep things alive as long as necessary.
If some T really requires references, but only into its own data, use a safe self-referential struct helper like ouroboros. (I believe this is similar to but more general than the suggestion in Aplet123's answer to this question.)
All of these strategies are independent of the DI container: they're ways to make a type satisfy the 'static lifetime bound ("contains no references except 'static ones").

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 can I specify a lifetime for closure arguments? [duplicate]

This question already has answers here:
How to declare a higher-ranked lifetime for a closure argument?
(3 answers)
Returning a higher-kinded closure that captures a reference
(1 answer)
Why does this closure require inlining or `dyn`? What does `dyn` do here?
(1 answer)
Expected bound lifetime parameter, found concrete lifetime [E0271]
(1 answer)
Closed last year.
Playpen link: http://is.gd/EpX6lM
I have a closure that takes a slice and returns a subslice of it. Compiling the following code on rust-1.0.0-beta-2 fails:
trait OptionalFirst {
fn optional_first<'a>(&self, x: &'a [usize]) -> &'a [usize];
}
impl<F> OptionalFirst for F where F: Fn(&[usize]) -> &[usize] {
fn optional_first<'a>(&self, x: &'a [usize]) -> &'a [usize] {
(*self)(x)
}
}
fn main() {
let bc: Box<OptionalFirst> = Box::new(
|x: &[usize]| -> &[usize] {
if x.len() != 0 {
&x[..1]
}
else {
&x[..0]
}
}) as Box<OptionalFirst>;
let a: [usize; 3] = [1, 2, 3];
let b: &[usize] = bc.optional_first(&a);
println!("{:?}", b);
}
I know how to define a lifetime in a closure's type (using for <'a>), but I don't know how to specify it in the closure's implementation.
Your implementation impl<F> OptionalFirst for F where F: Fn(&[usize]) -> &[usize] is expecting a bound lifetime parameter, for the constraint F: Fn(&[usize]) -> &[usize] is, expanded to full form: F: for<'a> Fn(&'a [usize]) -> &'a [usize].
That is, at the time you call the function, it will determine what values to select for the lifetime (they are generics).
A closure, however, cannot have any bound lifetime parameters; they are by stuck using concrete lifetime parameters. They lack the facility to wire output lifetimes to input lifetimes generically as you want: they are by very design concrete and not generic. I haven’t thought about this in great depth, but it might be possible to counteract this for generic lifetime parameters; it is not, however, something that is implemented as far as I am aware.
If you want something like this, try using a function rather than a closure. When you’re not using any of the environment there’s no benefit to using closures beyond the typically lower verbosity.
Here’s what you end up with:
fn bc(x: &[usize]) -> &[usize] {
if x.len() != 0 {
&x[..1]
} else {
&x[..0]
}
}
Playpen
You can create a closure with bound lifetime parameters, you just have to get the compiler to infer that type correctly. It can be done like this:
fn main() {
let bc: Box<Fn(&[usize]) -> &[usize]> = Box::new(
|x| {
if x.len() != 0 {
&x[..1]
}
else {
&x[..0]
}
});
let a: [usize; 3] = [1, 2, 3];
let b: &[usize] = bc(&a);
println!("{:?}", b);
}
However, what I don't know is how to cast it further into Box<OptionalFirst>.

How do I return a reference to a closure's argument from the closure?

I am a Rust newbie, and don't understand all the rules for lifetime elision and inference. I can't seem to get returning a reference into an argument from a closure to work, and the errors don't help much for someone with my amount of knowledge.
I can use a proper function with lifetime annotations in place of a closure, but can't figure out a way to annotate these lifetimes on the closure.
struct Person<'a> {
name: &'a str,
}
impl<'a> Person<'a> {
fn map<F, T>(&'a self, closure: F) -> T
where F: Fn(&'a Person) -> T
{
closure(self)
}
}
fn get_name<'a>(person: &'a Person) -> &'a str {
person.name
}
fn main() {
let p = Person { name: "hello" };
let s: &str = p.map(|person| person.name); // Does not work
// let s: &str = p.map(get_name); // Works
println!("{:?}", s);
}
And here is the compiler error:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:19:34
|
19 | let s: &str = p.map(|person| person.name); // Does not work
| ^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 19:33...
--> src/main.rs:19:34
|
19 | let s: &str = p.map(|person| person.name); // Does not work
| ^^^^^^^^^^^
note: ...so that expression is assignable (expected &str, found &str)
--> src/main.rs:19:34
|
19 | let s: &str = p.map(|person| person.name); // Does not work
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the method call at 19:18...
--> src/main.rs:19:19
|
19 | let s: &str = p.map(|person| person.name); // Does not work
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that pointer is not dereferenced outside its lifetime
--> src/main.rs:19:19
|
19 | let s: &str = p.map(|person| person.name); // Does not work
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
What is happening here, and how to change the closure for it to work?
I think I was confusing the lifetime of reference to the Person with the lifetime parameter of the struct (of the &str reference). This compiles:
struct Person<'a> {
name: &'a str,
}
impl<'a> Person<'a> {
fn map<F, T>(&self, closure: F) -> T
where F: Fn(&Person<'a>) -> T
{
closure(self)
}
}
fn get_name<'a>(person: &Person<'a>) -> &'a str {
person.name
}
fn main() {
let p = Person { name: "hello" };
println!("{:?}", p.map(|person| person.name));
println!("{:?}", p.map(get_name));
}
I'm not sure if my understanding of the lifetime annotations is correct, and perhaps someone else can pick apart the compiler error above. The language is extremely confusing.

How can I move a captured variable into a closure within a closure?

This code is an inefficient way of producing a unique set of items from an iterator. To accomplish this, I am attempting to use a Vec to keep track of values I've seen. I believe that this Vec needs to be owned by the innermost closure:
fn main() {
let mut seen = vec![];
let items = vec![vec![1i32, 2], vec![3], vec![1]];
let a: Vec<_> = items
.iter()
.flat_map(move |inner_numbers| {
inner_numbers.iter().filter_map(move |&number| {
if !seen.contains(&number) {
seen.push(number);
Some(number)
} else {
None
}
})
})
.collect();
println!("{:?}", a);
}
However, compilation fails with:
error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
--> src/main.rs:8:45
|
2 | let mut seen = vec![];
| -------- captured outer variable
...
8 | inner_numbers.iter().filter_map(move |&number| {
| ^^^^^^^^^^^^^^ cannot move out of captured outer variable in an `FnMut` closure
This is a little surprising, but isn't a bug.
flat_map takes a FnMut as it needs to call the closure multiple times. The code with move on the inner closure fails because that closure is created multiple times, once for each inner_numbers. If I write the closures in explicit form (i.e. a struct that stores the captures and an implementation of one of the closure traits) your code looks (a bit) like
struct OuterClosure {
seen: Vec<i32>
}
struct InnerClosure {
seen: Vec<i32>
}
impl FnMut(&Vec<i32>) -> iter::FilterMap<..., InnerClosure> for OuterClosure {
fn call_mut(&mut self, (inner_numbers,): &Vec<i32>) -> iter::FilterMap<..., InnerClosure> {
let inner = InnerClosure {
seen: self.seen // uh oh! a move out of a &mut pointer
};
inner_numbers.iter().filter_map(inner)
}
}
impl FnMut(&i32) -> Option<i32> for InnerClosure { ... }
Which makes the illegality clearer: attempting to move out of the &mut OuterClosure variable.
Theoretically, just capturing a mutable reference is sufficient, since the seen is only being modified (not moved) inside the closure. However things are too lazy for this to work...
error: lifetime of `seen` is too short to guarantee its contents can be safely reborrowed
--> src/main.rs:9:45
|
9 | inner_numbers.iter().filter_map(|&number| {
| ^^^^^^^^^
|
note: `seen` would have to be valid for the method call at 7:20...
--> src/main.rs:7:21
|
7 | let a: Vec<_> = items.iter()
| _____________________^
8 | | .flat_map(|inner_numbers| {
9 | | inner_numbers.iter().filter_map(|&number| {
10| | if !seen.contains(&number) {
... |
17| | })
18| | .collect();
| |__________________^
note: ...but `seen` is only valid for the lifetime as defined on the body at 8:34
--> src/main.rs:8:35
|
8 | .flat_map(|inner_numbers| {
| ___________________________________^
9 | | inner_numbers.iter().filter_map(|&number| {
10| | if !seen.contains(&number) {
11| | seen.push(number);
... |
16| | })
17| | })
| |_________^
Removing the moves makes the closure captures work like
struct OuterClosure<'a> {
seen: &'a mut Vec<i32>
}
struct InnerClosure<'a> {
seen: &'a mut Vec<i32>
}
impl<'a> FnMut(&Vec<i32>) -> iter::FilterMap<..., InnerClosure<??>> for OuterClosure<'a> {
fn call_mut<'b>(&'b mut self, inner_numbers: &Vec<i32>) -> iter::FilterMap<..., InnerClosure<??>> {
let inner = InnerClosure {
seen: &mut *self.seen // can't move out, so must be a reborrow
};
inner_numbers.iter().filter_map(inner)
}
}
impl<'a> FnMut(&i32) -> Option<i32> for InnerClosure<'a> { ... }
(I've named the &mut self lifetime in this one, for pedagogical purposes.)
This case is definitely more subtle. The FilterMap iterator stores the closure internally, meaning any references in the closure value (that is, any references it captures) have to be valid as long as the FilterMap values are being thrown around, and, for &mut references, any references have to be careful to be non-aliased.
The compiler can't be sure flat_map won't, e.g. store all the returned iterators in a Vec<FilterMap<...>> which would result in a pile of aliased &muts... very bad! I think this specific use of flat_map happens to be safe, but I'm not sure it is in general, and there's certainly functions with the same style of signature as flat_map (e.g. map) would definitely be unsafe. (In fact, replacing flat_map with map in the code gives the Vec situation I just described.)
For the error message: self is effectively (ignoring the struct wrapper) &'b mut (&'a mut Vec<i32>) where 'b is the lifetime of &mut self reference and 'a is the lifetime of the reference in the struct. Moving the inner &mut out is illegal: can't move an affine type like &mut out of a reference (it would work with &Vec<i32>, though), so the only choice is to reborrow. A reborrow is going through the outer reference and so cannot outlive it, that is, the &mut *self.seen reborrow is a &'b mut Vec<i32>, not a &'a mut Vec<i32>.
This makes the inner closure have type InnerClosure<'b>, and hence the call_mut method is trying to return a FilterMap<..., InnerClosure<'b>>. Unfortunately, the FnMut trait defines call_mut as just
pub trait FnMut<Args>: FnOnce<Args> {
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
In particular, there's no connection between the lifetime of the self reference itself and the returned value, and so it is illegal to try to return InnerClosure<'b> which has that link. This is why the compiler is complaining that the lifetime is too short to be able to reborrow.
This is extremely similar to the Iterator::next method, and the code here is failing for basically the same reason that one cannot have an iterator over references into memory that the iterator itself owns. (I imagine a "streaming iterator" (iterators with a link between &mut self and the return value in next) library would be able to provide a flat_map that works with the code nearly written: would need "closure" traits with a similar link.)
Work-arounds include:
the RefCell suggested by Renato Zannon, which allows seen to be borrowed as a shared &. The desugared closure code is basically the same other than changing the &mut Vec<i32> to &Vec<i32>. This change means "reborrow" of the &'b mut &'a RefCell<Vec<i32>> can just be a copy of the &'a ... out of the &mut. It's a literal copy, so the lifetime is retained.
avoiding the laziness of iterators, to avoid returning the inner closure, specifically.collect::<Vec<_>>()ing inside the loop to run through the whole filter_map before returning.
fn main() {
let mut seen = vec![];
let items = vec![vec![1i32, 2], vec![3], vec![1]];
let a: Vec<_> = items
.iter()
.flat_map(|inner_numbers| {
inner_numbers
.iter()
.filter_map(|&number| if !seen.contains(&number) {
seen.push(number);
Some(number)
} else {
None
})
.collect::<Vec<_>>()
.into_iter()
})
.collect();
println!("{:?}", a);
}
I imagine the RefCell version is more efficient.
It seems that the borrow checker is getting confused at the nested closures + mutable borrow. It might be worth filing an issue. Edit: See huon's answer for why this isn't a bug.
As a workaround, it's possible to resort to RefCell here:
use std::cell::RefCell;
fn main() {
let seen = vec![];
let items = vec![vec![1i32, 2], vec![3], vec![1]];
let seen_cell = RefCell::new(seen);
let a: Vec<_> = items
.iter()
.flat_map(|inner_numbers| {
inner_numbers.iter().filter_map(|&number| {
let mut borrowed = seen_cell.borrow_mut();
if !borrowed.contains(&number) {
borrowed.push(number);
Some(number)
} else {
None
}
})
})
.collect();
println!("{:?}", a);
}
I came across this question after I ran into a similar issue, using flat_map and filter_map. I solved it by moving the filter_map outside the flat_map closure.
Using your example:
let a: Vec<_> = items
.iter()
.flat_map(|inner_numbers| inner_numbers.iter())
.filter_map(move |&number| {
if !seen.contains(&number) {
seen.push(number);
Some(number)
} else {
None
}
})
.collect();

Resources