I'm stumped. I was not getting this error until I had to modify data stored in an Rc, so I added RefCell and used borrow(). The code has further details. This is with Rust 1.81 (the version available on OpenBSD 7.6).
The code is:
use sqlx::{Postgres, Transaction};
use std::cell::{Ref, RefCell};
use std::rc::Rc;
//This minimally reproduces the problem, but the actual complete code base with
//this compilation error is at github.com/onemodel/onemodel in the branch "wip",
//in core/src/model/entity.rs around line 540 (https://github.com/onemodel/onemodel/blob/wip/core/src/model/entity.rs). It has many compilation errors that I can better
//fix after resolving this one (and the one around line 747).
//The complete code is in process of being converted from Scala (commented out) to Rust.
//
//I can't use into_inner() here because of the "dyn Database". These errors did not occur before I
//added the call to borrow(), which was necessary due to use of RefCell, inside the Rc, because
//I added code that needs to write to the db struct's data.
//
//To build this, one must first run "cargo update url@2.5.4 --precise 2.3.1".
fn main() {
let pg = PostgreSQLDatabase {};
let db = Rc::new(RefCell::new(pg));
let entity = Entity { db, id: 0 };
let result = entity.add_quantity_attribute2(None);
println!(".");
result.unwrap()
}
struct Entity {
db: Rc<RefCell<dyn Database>>,
id: i64,
}
impl Entity {
fn add_quantity_attribute2<'a, 'b>(
&'a self,
//The compiler forced me to use this 'b and other generics due to reasons found in the full program
//if it is not clear enough here.
transaction: Option<Rc<RefCell<Transaction<'b, Postgres>>>>,
) -> Result<(), String>
where
'a: 'b,
{
let db: Ref<'b, dyn Database> = self.db.borrow();
let id: i64 = db.create_quantity_attribute(
transaction.clone(),
self.id,
)?;
Ok(QuantityAttribute::new2(
self.db.clone(),
transaction.clone(),
id,
))
}
}
pub struct QuantityAttribute {}
impl QuantityAttribute {
fn new2(
_db: Rc<RefCell<dyn Database>>,
_transaction: Option<Rc<RefCell<Transaction<Postgres>>>>,
_id: i64,
) {
()
}
}
trait Database {
fn create_quantity_attribute<'a, 'b>(
&'a self,
transaction: Option<Rc<RefCell<Transaction<'b, Postgres>>>>,
parent_id_in: i64,
) -> Result<i64, String>
where
'a: 'b;
}
struct PostgreSQLDatabase {}
impl Database for PostgreSQLDatabase {
fn create_quantity_attribute<'a, 'b>(
&'a self,
_transaction: Option<Rc<RefCell<Transaction<'b, Postgres>>>>,
_parent_id_in: i64,
) -> Result<i64, String>
where
'a: 'b,
{
Ok(0)
}
}
The full error message is:
error[E0597]: `db` does not live long enough
--> src/main.rs:41:23
|
31 | fn add_quantity_attribute2<'a, 'b>(
| -- lifetime `'b` defined here
...
40 | let db: Ref<'b, dyn Database> = self.db.borrow();
| -- binding `db` declared here
41 | let id: i64 = db.create_quantity_attribute(
| -^
| |
| _______________________borrowed value does not live long enough
| |
42 | | transaction.clone(),
43 | | self.id,
44 | | )?;
| |_________- argument requires that `db` is borrowed for `'b`
...
50 | }
| - `db` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
error: could not compile `my_cargo_app` (bin "my_cargo_app") due to 1 previous error
Here is the Cargo.toml required:
[package]
name = "my_cargo_app"
version = "0.1.0"
edition = "2021"
[dependencies]
# sqlx = { version = "0.6.3", features = [ "runtime-tokio-rustls", "postgres", "uuid" ] }
sqlx = { version = "0.6.3", features = [ "runtime-tokio-rustls", "postgres"] }