Here's a playground link that reproduces the error: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=86ec4f11f407f5d04a8653cc904f991b
I have a trait FooTraitMut that provides access to a specific range of data inside of BarStruct, and I want to generalize this trait so that it can access the same range on multiple BarStructs in lockstep. So I have a MutChannels trait that acts like a type-level function to produce the tuple of references that a visitor needs, e.g. (T, U) --> (&mut T, &mut U).
I haven't actually gotten to the point of using Channels2 because I can't get the simpler Channels1 case to work.
In the playground, the same is done for an immutable trait FooTraitRef, which works as intended. But the mutable one is broken due to an autoref lifetime issue. I think some kind of implicit transformation is happening to the lifetime of self, because I can inline the indexer function and it works fine.
Any help would be greatly appreciated.
The code in question:
struct BarStruct<T> {
data: [T; 1],
}
pub struct Channels1<T>(T);
pub struct Channels2<T, U>(T, U);
fn indexer(mut f: impl FnMut(usize)) {
f(0)
}
trait FooMutTrait {
type Data: for<'a> MutChannels<'a>;
fn foo<'a, F>(&'a mut self, f: F)
where
F: FnMut(<Self::Data as MutChannels<'a>>::Mut);
}
trait MutChannels<'a> {
type Mut;
}
impl<'a, T: 'a> MutChannels<'a> for Channels1<T> {
type Mut = &'a mut T;
}
impl<'a, T: 'a, U: 'a> MutChannels<'a> for Channels2<T, U> {
type Mut = (&'a mut T, &'a mut U);
}
impl<T> BarStruct<T> {
fn get_data_mut<'a>(&'a mut self, i: usize) -> &'a mut T {
&mut self.data[i]
}
}
impl<T> FooMutTrait for BarStruct<T>
where
T: 'static,
{
type Data = Channels1<T>;
#[inline]
fn foo<'a, F>(&'a mut self, mut f: F)
where
F: FnMut(<Self::Data as MutChannels<'a>>::Mut),
{
indexer(|i| f(self.get_data_mut(i)))
// This works.
// f(self.get_data_mut(0))
}
}
And the error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:85:28
|
85 | indexer(|i| f(self.get_data_mut(i)))
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 85:17...
--> src/lib.rs:85:17
|
85 | indexer(|i| f(self.get_data_mut(i)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `self`
--> src/lib.rs:85:23
|
85 | indexer(|i| f(self.get_data_mut(i)))
| ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the method body at 81:12...
--> src/lib.rs:81:12
|
81 | fn foo<'a, F>(&'a mut self, mut f: F)
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:85:23
|
85 | indexer(|i| f(self.get_data_mut(i)))
| ^^^^^^^^^^^^^^^^^^^^