我是否可以使用要求该类型为特征的泛型类型绑定?

时间:2016-10-07 16:40:06

标签: rust

我想声明一个接受特征对象的通用函数,只接受特征对象。我想要这个,因为我想键入擦除这些并将它们作为TraitObject对象传递到ABI边界。

这样写的函数将无法编译......

fn f<T: ?Sized>(t: &T) -> std::raw::TraitObject {
    unsafe { std::mem::transmute(t) }
}

...出现以下错误:

error[E0512]: transmute called with differently sized types: &T (pointer to T) to std::raw::TraitObject (128 bits)

我理解为什么编译器抱怨不同的大小:&T可以是指向具体类型的指针(如&i32),它是单指针(64位)或特征对象(比如&Display),它将是两个指针,其布局与std::raw::TraitObject(128位)相同。

只要&T是特征对象,此函数就可以正常,即T是特征。有没有办法表达这个要求?

3 个答案:

答案 0 :(得分:3)

不可能证明是消极的...但据我所知,答案是否定的,抱歉。

TraitObject的表示是不稳定的,特别是因为将来Rust可能能够将多个虚拟指针添加到单个数据指针(例如代表&(Display + Eq))。

同时,我通常使用低级内存技巧来读取虚拟指针和数据指针,然后自己构建TraitObject;通过致电mem::size_of来保护,以确保&T的{​​{1}}大小正确,因为*mut ()表示?Sized或不Sized(而非!Sized })。

答案 1 :(得分:3)

如果你use transmute_copy instead,你可以让编译器忽略大小不匹配。但是,这意味着您必须自己处理此类问题,例如:自己检查尺寸,如果不匹配可能会感到恐慌。不这样做会导致未定义的行为。

fn f<T: ?Sized>(t: &T) -> std::raw::TraitObject {
    assert!(std::mem::size_of::<&T>() == std::mem::size_of::<std::raw::TraitObject>());
    unsafe { std::mem::transmute_copy(&r) }
}

答案 2 :(得分:1)

相信 the answer is "no"

  

无法一般

引用所有特征对象

(强调我的)