考虑以下示例(操场链接):
struct Wrapper(String);
async fn foo(my_slice: &[Wrapper]) {
bar(my_slice).await; // Error!
}
async fn bar(string_slice: &[String]) { ... }
Run Code Online (Sandbox Code Playgroud)
我在编写foo
这样的代码时遇到了困难,以至于我可以在bar(my_slice)
不克隆的情况下调用my_slice
,因为String
没有实现Copy
.
我知道不安全的方法来做到这一点的:将一个#[repr(transparent)]
上Wrapper
和mem::transmute
它,但是我正在寻找方式完全安全的锈做到这一点。
我试图实现From
,但是切片一直被认为是外来类型,因此我遇到了孤立规则(外来类型上的外来特征实现),禁止我这样做。
不幸的是,我只需要修改的能力foo
或Wrapper
为bar
是自动生成的。
有没有办法&[Wrapper]
在&[String]
没有克隆的情况下安全地投射到?
不。类型系统没有谓词来表示“可以安全地转换”的想法,因此如果您的类型不是编译器本身可以强制转换的类型,则必须使用它unsafe
来执行。
但是,您不应该使用transmute
有效的指针强制转换。相反,将切片分解为一个指针和一个长度,并使用目标类型创建一个新切片。
#[repr(transparent)]
struct Wrapper(String);
async fn foo(my_slice: &[Wrapper]) {
let my_slice =
unsafe { std::slice::from_raw_parts(my_slice.as_ptr() as *const String, my_slice.len()) };
bar(my_slice).await;
}
Run Code Online (Sandbox Code Playgroud)
这比 using 稍微冗长一些transmute
,但它可以做的事情也更有限。transmute
是一种通用工具,需要比平时更多的照顾;将其保存在简单强制转换不起作用的情况下。
我正在寻找在完全安全的 Rust 中做到这一点的方法。
坚持使用安全的 Rust 通常是个好主意;然而,从不使用unsafe
意味着放弃一定程度的性能和灵活性,以换取在这种情况下不必考虑太多。unsafe
对我来说,这看起来是一个完美的用法:它可以封装在一个微小的、安全的函数中,并且很容易证明是正确的。但是,如果您决心避免unsafe
,则无法绕过clone
这些项目。
归档时间: |
|
查看次数: |
234 次 |
最近记录: |