如何从函数返回 &Path? [英] How do I return a &Path from a function?

查看:27
本文介绍了如何从函数返回 &Path?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解如何编写正确的 Rust 代码,但我认为我可能高估了编译器理解对象生命周期的能力.这是我期望的代码:

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();
}

当我尝试编译它时,我收到一个关于 &Path 上缺少生命周期说明符的错误.我知道如果这从调用者那里获取了一个引用参数,它将与该引用具有相同的生命周期.虽然在这里我期望的是生命周期将附加到我将结果分配给的变量.

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.

我知道可以显式添加生命周期,但我不知道如何在这种情况下应用它们.编译器建议尝试 'static 生命周期,但据我所知,这在这里没有意义,因为这个函数的返回值的来源不是静态的.

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.

现在,只是想看看如果我尝试编译其余代码会发生什么,我将返回类型从 &Path 更改为 PathBuf 并调用as_path()open() 中.这导致编译器输出这些错误:

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() 返回一个 Result 并且 SqliteConnection 中唯一的字段是一个 RefCell,所以我不明白这个关于字节数组的错误是从哪里来的.

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?

推荐答案

在您的第一种情况下,您正在创建一个值,然后尝试返回对它的引用.但是由于您没有将该值存储在任何地方,因此在函数结束后它会被销毁.如果它被允许,那将是一个释放后使用的错误.

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.

它建议返回 &'static Path 的原因是因为该函数没有在任何生命周期内参数化,因此唯一可以确定的生命周期比任何想要使用返回值的生命周期都长将是 'static.

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.

您是正确的,您需要直接返回 PathBuf 而不是 &Path.

You are correct that you need to return a PathBuf directly instead of an &Path.

我不太确定您为什么会收到 [u8] 大小的错误.

I'm not quite sure why you are getting the [u8] sized errors.

您根本不需要调用as_path()".SqliteConnection::open 接受一个实现 AsRef 的值(AsRef 有点像 Into),并且 PathBuf 确实实现了该特性.

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.

这篇关于如何从函数返回 &amp;Path?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆