rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.41k stars 12.59k forks source link

error[E0275]: overflow evaluating the requirement `<RefTFamily<T> as LifetimizedOutputFamily>::Output<'a> == _` #130728

Open JohnScience opened 2 weeks ago

JohnScience commented 2 weeks ago

I was trying to implement a generic SelfBorrowingClosure based on https://users.rust-lang.org/t/why-closure-cannot-return-a-reference-to-data-moved-into-closure/72655/6 but got a problem compiling the following piece of code:

pub trait LifetimizedOutputFamily {
    type Output<'a>
    where 
        Self::Output<'a>: 'a;
}

pub struct RefTFamily<T>(core::marker::PhantomData<*const T>);

impl<T> LifetimizedOutputFamily for RefTFamily<T>
{
    type Output<'a> = &'a T
    where
        T: 'a;
}

pub struct SelfBorrowingClosure<State, F, OutputFam>
where
    OutputFam: LifetimizedOutputFamily,
    F: Fn(&'_ State) -> <OutputFam as LifetimizedOutputFamily>::Output<'_>,
{
    pub state: State,
    pub call: F,
    pub output_family: core::marker::PhantomData<*const OutputFam>,
}

impl<State, F, OutputFam> SelfBorrowingClosure<State, F, OutputFam>
where
    OutputFam: LifetimizedOutputFamily,
    F: Fn(&'_ State) -> <OutputFam as LifetimizedOutputFamily>::Output<'_>,
{
    pub fn new(state: State, call: F) -> Self {
        Self {
            state,
            call,
            output_family: core::marker::PhantomData,
        }
    }

    pub fn call(&self) -> <OutputFam as LifetimizedOutputFamily>::Output<'_> {
        (self.call)(&self.state)
    }
}

Minimal Reproducible Example (MRE):

pub trait LifetimizedOutputFamily {
    type Output<'a>
    where 
        Self::Output<'a>: 'a;
}

pub struct RefTFamily<T>(core::marker::PhantomData<*const T>);

impl<T> LifetimizedOutputFamily for RefTFamily<T>
{
    type Output<'a> = &'a T
    where
        T: 'a;
}

Error:

error[E0275]: overflow evaluating the requirement `<RefTFamily<T> as LifetimizedOutputFamily>::Output<'a> == _`
  --> src\lib.rs:11:5
   |
11 |     type Output<'a> = &'a T
   |     ^^^^^^^^^^^^^^^
JohnScience commented 2 weeks ago

I can do that for a concrete type:

mod workaround {
    pub struct SelfBorrowingClosureReturningStdFmtArguments<
        State,
        F : Fn(&'_ State) -> std::fmt::Arguments<'_>
    > {
        pub state: State,
        pub closure: F,
    }

    impl<State, F> SelfBorrowingClosureReturningStdFmtArguments<State, F>
    where
        F : Fn(&'_ State) -> std::fmt::Arguments<'_>,
    {
        pub fn new(state: State, closure: F) -> Self {
            Self { state, closure }
        }

        pub fn call (self: &'_ SelfBorrowingClosureReturningStdFmtArguments<State, F>)
            -> std::fmt::Arguments<'_>
        {
            (self.closure)(&self.state)
        }
    }
}

However, even my adhoc workaround didn't help me:

I ended up creating a simple lib for what I wanted to do: https://crates.io/crates/display_with