Closed as not planned
Description
I'm having a hard time minimizing this code sample, so sorry in advance.
The real issue I'm facing is #111662, so please see my comment for some context.
However, since that issue isn't fixed, I needed a workaround.
Here's the basic jist of my workaround:
fn main() {
// ERROR:
let _c = |b: S<'_>| -> &() { b.thing() }; //~ ERROR lifetime may not live long enough
// WORKAROUND:
let _c = fix_lifetime(|b: S| b.thing());
}
// Let's help the compiler out a little:
fn fix_lifetime<F, T>(f: F) -> F
where
F: for<'a> FnOnce(S<'a>) -> &'a T,
{
f
}
struct S<'a>(&'a ());
impl<'a> S<'a> {
fn thing(self) -> &'a () {
self.0
}
}
This workaround works for the provided example and I'm guessing 99% of other situations.
But, my actual issue is a bit more complicated so I get a:
error: higher-ranked lifetime error
--> rearch/src/side_effects.rs:13:5
|
13 | fix_lifetime(move |register: SideEffectRegistrar| register.raw(initial))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
No further information is provided.
Full copy of the problematic code
// This trait is the main problem. It is equivalent to FnOnce(SideEffectRegistrar) -> T
pub trait SideEffect {
type Api<'a>;
fn build<'a>(self, registrar: SideEffectRegistrar<'a>) -> Self::Api<'a>;
}
impl<T, F: FnOnce(SideEffectRegistrar) -> T> SideEffect for F {
type Api<'a> = T;
fn build<'a>(self, registrar: SideEffectRegistrar<'a>) -> Self::Api<'a> {
self(registrar)
}
}
pub fn raw<T: Send + 'static>(
initial: T,
) -> impl for<'a> SideEffect<
Api<'a> = (
&'a mut T,
impl Fn(Box<dyn FnOnce(&mut T)>) + Clone + Send + Sync,
),
> {
fix_lifetime(move |register: SideEffectRegistrar| register.raw(initial)) // ------------------- ERROR HERE
}
// Workaround from above to try to fix the underlying issue.
fn fix_lifetime<F, T, R>(f: F) -> F
where
F: for<'a> FnOnce(SideEffectRegistrar<'a>) -> (&'a mut T, R),
{
f
}
// Not sure if this is needed, but here it is just in case:
pub struct SideEffectRegistrar<'a> {
side_effect: &'a mut OnceCell<Box<dyn Any + Send>>,
rebuilder: Box<dyn SideEffectRebuilder>,
}
impl<'a> SideEffectRegistrar<'a> {
// Other methods left out for brevity.
pub(crate) fn raw<T>(
self,
initial: T,
) -> (
&'a mut T,
impl Fn(Box<dyn FnOnce(&mut T)>) + Clone + Send + Sync + 'static,
)
where
T: Send + 'static,
{
self.side_effect.get_or_init(|| Box::new(initial));
let data = self
.side_effect
.get_mut()
.expect(PREVIOUS_INIT_FAILED_MSG)
.downcast_mut::<T>()
.unwrap_or_else(|| panic!("{}", EFFECT_FAILED_CAST_MSG));
let rebuild = move |mutation: Box<dyn FnOnce(&mut T)>| {
(self.rebuilder)(Box::new(|data| {
let data = data
.downcast_mut::<T>()
.unwrap_or_else(|| panic!("{}", EFFECT_FAILED_CAST_MSG));
mutation(data);
}));
};
(data, rebuild)
}
}
Meta
Tested on nightly.