E0139

未匹配的标注

注意:编译器不再触发此代码

Rust 的类型转换有各种严格的限制;例如被转换的类型必须具有相同的大小。要应用这些限制,编译器必须知道要转换的确切类型。当涉及类型参数时,不能总是这样做。

例如,不允许执行以下操作:

use std::mem::transmute;

struct Foo<T>(Vec<T>);

fn foo<T>(x: Vec<T>) {
    // 在 Vec<T> 和 Foo<F> 间转换
    let y: Foo<T> = unsafe { transmute(x) };
    // do something with y
}

在这种特定情况下,转换很有可能没什么危害(但这并非是 Rust 可以保证的)。然而,当对齐和枚举优化( enum optimizations ) 出现时,大小很可能与不同的类型参数替换匹配,也可能不匹配( it’s quite likely that the sizes may or may not match with different type parameter substitutions )。不可能检查所有的类型,因此 transmute() 只接受没有任何未替换类型参数的类型。

如果需要这样做,很可能是一种错误的做法。请记住,Rust 不能保证不同结构的布局(即便是具有相同声明的两个结构也可能具有不同的布局)。如果有一种解决方案可以完全避免这种转换,请试着用该方案。

如果可能的话,通过为每种可能的类型替换编写单态化函数代码,可以使用 trait 来很清晰简便地做到这点。例如:

use std::mem::transmute;

struct Foo<T>(Vec<T>);

trait MyTransmutableType: Sized {
    fn transmute(_: Vec<Self>) -> Foo<Self>;
}

impl MyTransmutableType for u8 {
    fn transmute(x: Vec<u8>) -> Foo<u8> {
        unsafe { transmute(x) }
    }
}

impl MyTransmutableType for String {
    fn transmute(x: Vec<String>) -> Foo<String> {
        unsafe { transmute(x) }
    }
}

// ... 对于您打算转换的类型,更为简单。

fn foo<T: MyTransmutableType>(x: Vec<T>) {
    let y: Foo<T> = <T as MyTransmutableType>::transmute(x);
    // do something with y
}

每个 impl 都会像往常一样在转换中检查大小是否匹配,因为没有涉及未绑定的类型参数,所以应该编译,除非其中一个 impl 中存在大小不匹配。

也可以手动转换

unsafe {
    ptr::read(&v as *const _ as *const SomeType) // `v` 转换为 `SomeType`
}

注意,这不会 move v (与 transmute 不同),并且可能需要调用 mem::forget(v),以防调用析构函数。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
上一篇 下一篇
贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~