Reborrowing via a trait?

Thanks, this is exactly the kick in the brainstem I needed. I ended up with this:

pub trait WithExecutor<'e> {
    type Executor: Executor<'e, Database = sqlx::postgres::Postgres>;

    fn executor(&'e mut self) -> Self::Executor;
}

impl<'p> WithExecutor<'p> for Repository<sqlx::postgres::PgPool> {
    type Executor = &'p sqlx::postgres::PgPool;

    fn executor(&'p mut self) -> Self::Executor {
        &self.executor
    }
}

impl<'t, 'c> WithExecutor<'t> for Repository<sqlx::Transaction<'c, sqlx::Postgres>>
where
    'c: 't,
{
    type Executor = &'t mut sqlx::Transaction<'c, sqlx::Postgres>;

    fn executor(&'t mut self) -> Self::Executor {
        &mut self.executor
    }
}

impl<'e, T> Repository<T>
where
    Self: WithExecutor<'e>,
{
    pub async fn submit<R, N, O, I>(
        &'e mut self,
        submission: Submission<R, N, O, I>,
    ) -> Result<Filed<R, N, O, I>>
    where
        R: Submit + Unpin + Send,
        N: Serialize + DeserializeOwned,
        O: Serialize + DeserializeOwned,
        I: Serialize + DeserializeOwned,
    {
        let submission = submission.into_storage()?;
        let result = R::submit(submission).fetch_one(self.executor()).await?; // <-- the troublesome line from my original post
        let result = result.into_app()?;

        Ok(result)
    }
}

It has some ergonomics issues, but nothing insurmountable. Thanks a ton for reminding me that this is an option.

2 Likes