考虑以下示例(playground link):
struct Wrapper(String);
async fn foo(my_slice: &[Wrapper]) {
bar(my_slice).await; // Error!
}
async fn bar(string_slice: &[String]) { ... }
我在编写foo
时遇到了困难,这样我就可以在不克隆my_slice
的情况下调用bar(my_slice)
,因为String
没有实现Copy
。
我知道这样做的不安全方法:将#[repr(transparent)]
放在Wrapper
和mem::transmute
上,但我正在寻找在完全安全的Rust中做到这一点的方法。
我尝试过实现From
,但是切片总是被认为是外来类型,因此我遇到了孤儿规则(在外来类型上实现外来trait),禁止我这样做。
不幸的是,我只能修改foo
或Wrapper
,因为bar
是自动生成的。
有没有办法在不克隆的情况下安全地将&[Wrapper]
转换为&[String]
?
2条答案
按热度按时间tyky79it1#
类型系统没有 predicate 来表示“可以安全地转换”的思想,所以如果你的类型不能被编译器本身强制转换,你必须使用
unsafe
。但是,您不应该将
transmute
用于实际上是指针转换的对象。相反,将切片分解为指针和长度,并使用目标类型创建一个新切片。这比使用
transmute
稍微详细一些,但它的功能也更有限。transmute
是一个通用工具,需要比通常更多的照顾;把它留到简单转换不起作用的情况下。我正在寻找在完全安全的Rust中做到这一点的方法。
坚持安全的Rust通常是一个好主意;然而,never 使用
unsafe
意味着放弃某种程度的性能和灵活性,以换取在这种情况下不必考虑太多。在我看来,这是对unsafe
的完美使用:它可以被封装在一个微小的、安全的函数中,并且很容易证明它是正确的。但是如果你决心避免unsafe
,那么就没有办法绕过clone
。nkoocmlb2#
std中没有任何东西(期待safe transmute),但您可以使用
bytemuck
crate来安全地执行此操作: