我试图理解如何编写正确的Rust代码,但我想我可能高估了编译器理解对象生命周期的能力.这是我期望它工作的代码:
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();
}
Run Code Online (Sandbox Code Playgroud)
当我尝试编译它时,我得到一个关于缺少生命周期说明符的错误&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() }
^~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
SqliteConnection::open()返回一个Result<SqliteConnection, SqliteError>,里面唯一的字段SqliteConnection是a RefCell,所以我不明白这个字节数组的错误来自哪里.
那么,为什么事情没有按照我的预期发挥作用以及编写此代码最生锈的方式是什么?
在第一种情况下,您正在创建一个值,然后尝试返回对它的引用.但是,由于您没有将该值存储在任何位置,因此在函数结束后会被销毁.如果它被允许,它将是一个免费使用后的bug.
它建议返回a的原因&'static Path是因为函数没有在任何生命周期中进行参数化,所以你可以确定的唯一生命周期将超过任何想要使用返回值的东西'static.
你是正确的,你需要PathBuf直接返回而不是&Path.
我不太确定你为什么会遇到[u8]大小错误.
您根本不需要调用"as_path()".SqliteConnection::open获取实现的值AsRef<Path>(AsRef有点像Into),并PathBuf实现该特征.