我试图理解如何编写正确的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();
}
当我尝试编译时,我收到有关&Path
上缺少生命周期说明符的错误。我知道如果这从调用者那里获取了一个引用参数,它将与该引用具有相同的生命周期。虽然我期待的是生命周期将附加到我将结果赋给的变量。
我知道可以明确添加生命周期,但在这种情况下我不知道如何应用它们。编译器建议尝试'static
生命周期,但据我所知,这在这里没有意义,因为此函数的返回值的来源不是静态的。
现在,只是为了试着看看如果我尝试编译剩下的代码会发生什么,我将返回类型从&Path
更改为PathBuf
并在{{as_path()
中调用open()
1}}。这导致编译器输出这些错误:
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
,所以我不明白有关字节数组的错误来自哪里从
那么,为什么没有像我期望的那样工作,以及编写此代码最生锈的方式是什么?
答案 0 :(得分:7)
在第一种情况下,您正在创建一个值,然后尝试返回对它的引用。但是由于你不是在任何地方存储这个值,它会在函数结束后被破坏。如果允许的话,那就是免费使用后的错误。
它建议返回&'static Path
的原因是因为该函数在任何生命周期内都没有参数化,因此唯一可以确定任何想要使用返回值的生命周期为{{1 }}
你是正确的,你需要直接返回'static
而不是PathBuf
。
我不太清楚为什么会收到&Path
大小的错误。
你不需要打电话给#34; as_path()&#34;一点都不[u8]
采用实现SqliteConnection::open
的值(AsRef<Path>
有点像AsRef
),Into
确实实现了该特征。