有一個可變的參考。
如果更改transaction
這樣:
fn transaction(&mut self) -> Transaction {
let _:() = self;
Transaction{conn: self}
}
你會看到,與編譯器錯誤:
= note: expected type `()`
= note: found type `&mut Connection`
所以self
是&mut Connection
類型...一個可變參考。然後,您將此內容傳遞給從此函數返回的Transaction
實例。
這意味着您的可變借存在的trans
壽命(由我添加花括號以示借用的範圍):
let mut trans = db_conn.transaction();
{ // <-------------------- Borrow starts here
let mut records_without_sync = 0_usize;
const MAX_RECORDS_WITHOUT_SYNC: usize = 100;
loop {
//do something
records_without_sync += 1;
if records_without_sync >= MAX_RECORDS_WITHOUT_SYNC {
trans.commit();
records_without_sync = 0;
trans = db_conn.transaction();// <--- ####### D'oh! Still mutably borrowed
}
}
} // <-------------------- Borrow ends here
如果你正在尋找這種parent-><-child
設定的,我認爲你必須達到Rc<RefCell>
。
具體而言,引用的Rc
會計算您通過連接的次數,並且RefCell
可以在運行時跟蹤借用,而不是編譯時。是的,這意味着如果你在運行時嘗試並可變地借用它兩次,你會感到恐慌。不知道更多關於你的架構,很難說這是否合適。
Here is my solution anyway:
use std::cell::RefCell;
use std::rc::Rc;
struct Connection {}
impl Connection {
fn do_something_mutable(&mut self) {
println!("Did something mutable");
}
}
type Conn = Rc<RefCell<Connection>>;
struct Transaction {
conn: Conn,
}
impl Transaction {
fn new(connection: Conn) -> Transaction {
Transaction { conn: connection }
}
fn commit(mut self) {
self.conn.borrow_mut().do_something_mutable();
}
}
fn main() {
let db_conn = Rc::new(RefCell::new(Connection {}));
let mut trans = Transaction::new(db_conn.clone());
let mut records_without_sync = 0_usize;
const MAX_RECORDS_WITHOUT_SYNC: usize = 100;
loop {
//do something
records_without_sync += 1;
if records_without_sync >= MAX_RECORDS_WITHOUT_SYNC {
trans.commit();
records_without_sync = 0;
trans = Transaction::new(db_conn.clone());
break; // Used to stop the loop crashing the playground
}
}
}
最終,[你的代碼應該只是工作(https://internals.rust-lang.org/t/non-lexical-lifetimes-based-on-liveness/3428) ,但Rust還沒有。 –