Я пытаюсь понять, как писать правильный код ржавчины, но я думаю, что я могу переоценить способность компилятора понять времена жизни моих объектов. Это код, как я ожидал, что он работает:Как вернуть & & путь из функции?
use std::path::Path;
use std::env;
use rusqlite::SqliteConnection;
struct SomeDatabase {
conn: SqliteConnection,
}
impl SomeDatabase {
fn getPath() -> &Path {
let path = env::home_dir().unwrap();
path.push("foo.sqlite3");
path.as_path()
}
fn open() -> SomeDatabase {
let path = SomeDatabase::getPath()
SomeDatabase { conn: SqliteConnection::open(path).unwrap() }
}
}
fn main() {
let db = SomeDatabase::open();
}
Когда я пытаюсь скомпилировать это я получаю сообщение об ошибке о пропавшем пожизненном спецификаторе на &Path
. Я знаю, если бы это взяло ссылочный параметр от вызывающего, это заняло бы ту же жизнь, что и эта ссылка. Здесь, хотя я ожидал, что время жизни будет привязано к переменной, которой я присваиваю результат.
Я знаю, что жизнь может быть добавлена явно, но я не знаю, как их применять в этом случае. Компилятор предлагает попробовать время жизни 'static
, но это не имеет смысла здесь, насколько я знаю, потому что источник возвращаемого значения этой функции не является статическим.
Теперь, просто попытаться посмотреть, что случилось, если бы я попытался собрать остальную часть кода, я изменил тип возвращаемого из &Path
в PathBuf
и называется as_path()
в open()
. Это вызвало компилятор для вывода этих ошибок:
src\main.rs:22:30: 22:52 error: the trait `core::marker::Sized` is not implemented for the type `[u8]` [E0277]
src\main.rs:22 SomeDatabase { conn: SqliteConnection::open(path).unwrap() }
^~~~~~~~~~~~~~~~~~~~~~
src\main.rs:22:30: 22:52 note: `[u8]` does not have a constant size known at compile-time
src\main.rs:22 SomeDatabase { conn: SqliteConnection::open(path).unwrap() }
^~~~~~~~~~~~~~~~~~~~~~
SqliteConnection::open()
возвращает Result<SqliteConnection, SqliteError>
и единственное поле внутри SqliteConnection
является RefCell
, так что я не понимаю, где эта ошибка о массиве байт откуда.
Итак, почему не все работает так, как я ожидаю, и какой самый ржавый способ написать этот код?
Я понимаю, что в первом случае я возвращаю ссылку на что-то, созданное внутри функции, но если я сделаю getPath() функцией-членом SomeDatabase, компилятор достаточно умен, чтобы удерживать & Path до экземпляра SomeDatabase выходит за рамки. Я спрашиваю, есть ли способ сообщить компилятору, что время жизни ссылки принадлежит функции, вызывающей getPath() (в случае, когда getPath() является связанной функцией). Код жизненного цикла должен быть до тех пор, пока переменная, содержащая ссылку, не выходит из области действия в open(). –
Также нужно добавить, что если я оставил as_path(), я получаю ошибку с несогласованными типами: «expected» & _ ', found' std :: path :: PathBuf '(expected & -ptr, found struct' std :: path :: PathBuf ') –
@AustinWagner Переменная 'path' определяется в теле метода' getPath() ', его время жизни заканчивается в конце области действия этого тела функции, если вы не вернете его. чтобы избежать этого правила. В вашем случае нет альтернативы возврату функции 'PathBuf' для' getPath() '. – Levans