So, I have the following trait Input
:
trait Input: Sized {
// This should be Self but with a generic lifetime
// I tried it with FnOnce(Self), but the the impl Input for &[i32] doesn't
// work as the lifetime of the arg is shorter than the one of Self
type Mapped<'a>;
fn with_input<F>(self, f: F)
where
for<'a> F: FnOnce(Self::Mapped<'a>);
}
Input
is basically a trait which is implemented by a specific value or slices/arrays of that value (e.g. &[[i32; N]]
could be an input). Calling with_input
should construct a value that has the same "shape" as Self
(which currently means that slices and array have the same length) and passes this to the closure.
Now I wish to implement Input
on tuples of values which implement Input
.
impl<I1: Input, I2: Input> Input for (I1, I2)
{
type Mapped<'a> = (I1::Mapped<'a>, I2::Mapped<'a>);
fn with_input<F>(self, f: F)
where
for<'a> F: FnOnce(Self::Mapped<'a>),
{
self.0.with_input(|i1| {
self.1.with_input(|i2| {
f((i1, i2));
})
})
}
}
Unfortunately, this fails to compile with the error:
error[E0521]: borrowed data escapes outside of closure
--> src/main.rs:78:17
|
76 | self.0.with_input(|i1| {
| -- `i1` declared here, outside of the closure body
77 | self.1.with_input(|i2| {
| -- `i2` is a reference that is only valid in the closure body
78 | f((i1, i2));
| ^^^^^^^^^^^ `i2` escapes the closure body here
error[E0521]: borrowed data escapes outside of closure
--> src/main.rs:78:17
|
76 | self.0.with_input(|i1| {
| --
| |
| `i1` is a reference that is only valid in the closure body
| has type `<I1 as Input>::Mapped<'1>`
77 | self.1.with_input(|i2| {
78 | f((i1, i2));
| ^^^^^^^^^^^
| |
| `i1` escapes the closure body here
| argument requires that `'1` must outlive `'static`
I'm not sure where the problem lies. Curiosly, the impl for a single element tuple works, so the nested closures must be part of the problem. I've also tried to implement the trait without the GAT and receiving Self
as the argument to the closure of with_input
but this breaks the implementation for &[i32]
.
The code plus additional impls are here: Playground.
I'd be really happy if someone could help me out. I've already spent quite some time banging my head against the wall on this and similar problems.