I've been working with Rust for awhile, but I still have more to learn.
I've realized that I have duplicate code and I want to see if I can refactor it using generics and traits. This code is used to generate a sqlx::query based on a REST API request. The struct T implements IntoSql which has a method, SqlArray, that creates an array [(U, bool); N]. U is an enum representing the Columns in the MySql table and implements Into<&str>.
The sql_array method just looks at the values in the struct and calls .is_some() on them and if they are some, they are added to the query. So if the request contains:
{
"foo": "hello",
"bar": "world"
}
The sql would look like:
UPDATE table
SET foo = "hello", bar = "world"
WHERE id = ?;
When U is a generic then I get the error: fields_arr does not live long enough (see "fn update_new" in the playground), but when I specify U's type (e.g. User) then I don't get that error (see "fn update"). Any ideas how I can fix this lifetime issue?
Edit: Removed Rust code from the post as it was moved to the playground
Please provide a complete example in the Playground that reproduces your problem. This is too much code ans complexity for us to be able to guess what the root cause is.
I would assume the str representation can only be compile time constants, if so, the easiest fix probably is to explicit use &'static str.
these two line combined is the main cause of the lifetime error. I don't know what your exact use cases look like, but for this example snippet, I think the following bound should be sufficient to satisfy the borrow checker:
pub async fn update<T, U, const N: usize>(
id: u32,
t: T,
table_name: &str,
pool: &MySqlPool,
) -> Result<(), Error>
where
T: IntoSql<U, N, SqlArray = [(U, bool); N]>,
for <'a> &'a U: Into<&'a str>,
{
//...
}
but I suggest you define your custom trait instead of using Into<&str> as bound, something like: