如何表示返回的关联类型实现了特征?

时间:2016-02-11 15:48:43

标签: generics rust traits

这是显示我的问题的抽象示例,从我尝试重构某些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 })
    }
}

但是,如果我使用特征对象,我无法为ReturnGenStruct<i32>编写GenStruct<u32>的专门实现。

编译器能够识别出我实现了GenStruct<M: Marker>还是我的代码不是惯用的Rust?如果我的代码不是惯用的,那么编写它的正确方法是什么?

2 个答案:

答案 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 { } } } 实施MMarker实施GenStruct<M>的{​​{1}}说法的正确方法。无论某人如何或在何处实施这些特征都无关紧要,因为有保证是实施。

  

我无法编写专门的实现

这是正确的,现在。有一个正在进行的RFC,RFC 1020: impl specialization旨在允许在这些情况下进行专业化。