'Generic typed borrowed value does not live long enough in match
I have this function for quick SQL queries those only expect one value from the DB. I import the postgres 0.19.3 library.
fn psql_query<'a, T>(db: &str, query: &str) -> Result<T, postgres::Error>
where
T: postgres::types::FromSql<'a>,
{
let client = Client::connect(&format!("host=localhost user=postgres password={} dbname={}", get_password(), db), NoTls);
match client {
Ok(mut client) => {
match client.query_one(query, &[]) {
Ok(row) => Ok(row.get(0)),
Err(e) => Err(e)
}
}
Err(e) => Err(e)
}
}
Purpose: connect to DB, return Err() if unsuccessful; then execute query, then return Ok(value) or Err() if something went wrong. The caller can be sure to either get the requested value or the error why it went wrong. Originally I had this very same function with return type Result<String, Error> and it worked! Then I realized that maybe I need to query other data types from the DB and thought to utilize generic types instead of implementing separate functions. When I modified the function to use generic types, I started getting the following error:
error[E0597]: `row` does not live long enough
--> src/hc.rs:108:31
|
100 | fn psql_query<'a, T>(db: &str, query: &str) -> Result<T, postgres::Error>
| -- lifetime `'a` defined here
...
108 | Ok(row) => Ok(row.get(0)),
| ^^^^^^^^^^- `row` dropped here while still borrowed
| |
| borrowed value does not live long enough
| argument requires that `row` is borrowed for `'a`
So... why does row need to survive any longer? I mean, I just want the return value from get() packed into Ok(). Since this value will be owned and returned, row and client can be dropped. Even the carets show that row would be dropped after get(0) is evaluated, when I don't need it anymore. If get() would return a slice or reference that ties the return value to row, I would understand, but I don't think this is the case. Why it worked when it was String-only? How can I fix this?
(The postgres::types::FromSql<'a> and the 'a lifetime was required by Row.get().)
Solution 1:[1]
If
get()would return a slice or reference that ties the return value torow, I would understand, but I don't think this is the case.
That can be the case; the returned type from get() must implement FromSql<'a> where 'a is the lifetime of the Row. However, the exact type of value returned is T.
The compiler is complaining because the 'a specified by the caller must be longer than the lifetime of the row. Your code is effectively saying that the row must live for at least as long as the caller-supplied lifetime, which is impossible.
The most straightforward way to fix this is to say that T must implement FromSql<'a> for any possible lifetime 'a which you can do with a higher-rank trait bound (for):
fn psql_query<T>(db: &str, query: &str) -> Result<T, postgres::Error>
where T: for <'a> postgres::types::FromSql<'a>
{
...
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
