I'm trying to understand how to write proper Rust code, but I think I may be overestimating the power of the compiler's ability to understand the lifetimes of my objects. This is the code as I expected it to work:
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();
}
When I try to compile this, I get an error about a missing lifetime specifier on &Path
. I know if this took a reference parameter from the caller, it would take on the same lifetime as that reference has. Here though what I was expecting is that the lifetime would be attached to the variable I am assigning the result to.
I know lifetimes can be added explicitly, but I don't know how to apply them in this case. The compiler suggests trying the 'static
lifetime, but that doesn't make sense here as far as I know because the source of this function's return value isn't static.
Now, just to try to see what happened if I tried to compile the rest of the code, I changed the return type from &Path
to PathBuf
and called as_path()
in open()
. This caused the compiler to output these errors:
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()
returns a Result<SqliteConnection, SqliteError>
and the only field inside SqliteConnection
is a RefCell
, so I don't understand where this error about a byte array is coming from.
So, why aren't things working as I expect and what is the most Rusty way to write this code?
Tell the clerk you want to return the item. Go to the returns department if there is one, or to a cashier. Smile and explain that you want to return an item and why. Remember to be friendly.
Conducting a return with a QR code is simple. Towards the end of a normal return flow, a shopper will now have the option to select between Print & Shop, or the new Scan & Go tab in a new Choose your return option step. After selecting Scan & Go, the shopper would click on "Click here to find your closest location".
In your first case, you are creating a value and then trying to return a reference to it. But since you aren't storing that value anywhere, it gets destroyed after the function ends. If it was allowed, it'd be a use-after-free bug.
The reason it suggested returning a &'static Path
is because the function isn't parameterized over any lifetimes, so the only lifetime you can be sure outlives anything that wants to use the return value would be 'static
.
You are correct that you need to return a PathBuf
directly instead of an &Path
.
I'm not quite sure why you are getting the [u8]
sized errors.
You don't need to call "as_path()" at all. SqliteConnection::open
takes a value that implements AsRef<Path>
(AsRef
is sort of like Into
), and PathBuf
does implement that trait.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With