这是显示我的问题的抽象示例,从我尝试重构某些Rust代码并同时学习Rust中提取。
struct GenStruct<T> {
field: T,
}
trait Marker {}
trait Return {}
impl Marker for i32 {}
impl Marker for u32 {}
// actually implement `Return` for GenStruct<M: Marker>,
// but compiler don't recognize that
impl Return for GenStruct<i32> {}
impl Return for GenStruct<u32> {}
struct Fake;
trait Trait<M: Marker> {
type Ret: Return;
fn meth(m: M) -> Self::Ret;
}
impl<M: Marker> Trait<M> for Fake {
type Ret = GenStruct<M>;
fn meth(m: M) -> GenStruct<M> {
GenStruct { field: m }
}
}
输出:
error[E0277]: the trait bound `GenStruct<M>: Return` is not satisfied
--> src/lib.rs:23:17
|
23 | impl<M: Marker> Trait<M> for Fake {
| ^^^^^^^^ the trait `Return` is not implemented for `GenStruct<M>`
|
编译器无法识别我实际为Return
实施GenStruct<M>
,其中M为Marker
。为了解决这个问题,我可以写一些类似的东西:
trait Marker {
fn is_i32() -> bool;
}
trait Return {
fn ret();
}
impl Marker for i32 {
fn is_i32() -> bool {
true
}
}
impl Marker for u32 {
fn is_i32() -> bool {
false
}
}
// compiler is satisfied by such implementation
impl<M: Marker> Return for GenStruct<M> {
fn ret() {
if M::is_i32() {
} else {
}
}
}
或使用特质对象:
impl<M: Marker> Return for GenStruct<M> {}
trait Trait<'a, M: Marker + 'a> {
fn meth(m: M) -> Box<Return + 'a>;
}
impl<'a, M: Marker + 'a> Trait<'a, M> for Fake {
fn meth(m: M) -> Box<Return + 'a> {
Box::new(GenStruct { field: m })
}
}
但是,如果我使用特征对象,我无法为Return
和GenStruct<i32>
编写GenStruct<u32>
的专门实现。
编译器能够识别出我实现了GenStruct<M: Marker>
还是我的代码不是惯用的Rust?如果我的代码不是惯用的,那么编写它的正确方法是什么?
答案 0 :(得分:6)
使用where
子句,我们可以在通用impl
上添加其他约束,以便仅在GenStruct<M>
确实实现Return
时才适用。
impl<M: Marker> Trait<M> for Fake
where
GenStruct<M>: Return,
{
type Ret = GenStruct<M>;
fn meth(m: M) -> GenStruct<M> {
GenStruct { field: m }
}
}
Rust 1.33甚至通过帮助文本表示:
= help: consider adding a `where GenStruct<M>: Return` bound
答案 1 :(得分:3)
% heavisideOrigin1.m function y = heavisideOrigin1(x) y = round(heaviside(x)); end % ... y = heavisideOrigin1(-1:1) % prints y = 0 1 1
为什么您认为您正在为// actually implement `Return` for GenStruct<M: Marker>,
// but compiler don't recognize that
impl Return for GenStruct<i32> {}
impl Return for GenStruct<u32> {}
实施Return
?这仅针对两种特定变体实现。实现特征的类型不是封闭集;任何人都可以在将来添加特征的新实现。 Rust设计师不希望允许下游板条箱的更改影响您的箱子的编译 - 这种方式就是疯狂!
GenStruct<M: Marker>
这是对每个impl<M: Marker> Return for GenStruct<M> {
fn ret() {
if M::is_i32() { } else { }
}
}
实施M
,Marker
实施GenStruct<M>
的{{1}}说法的正确方法。无论某人如何或在何处实施这些特征都无关紧要,因为有保证是实施。
我无法编写专门的实现
这是正确的,现在。有一个正在进行的RFC,RFC 1020: impl specialization旨在允许在这些情况下进行专业化。