如何表示返回的关联类型实现了特征?
How to express that a returned associated type implements a trait?
这是显示我的问题的抽象示例,提取自我重构一些 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>`
|
编译器没有识别出我实际上为每个 GenStruct<M>
实现了 Return
,其中 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 })
}
}
但是,如果我使用特征对象,我无法为 GenStruct<i32>
和 GenStruct<u32>
.
编写 Return
的专门实现
编译器是否能够识别出我实现了 GenStruct<M: Marker>
或者我的代码不是惯用的 Rust?如果我的代码不符合地道,那么正确的写法是什么?
使用 where
子句,我们可以在泛型 impl
上添加额外的约束,这样它仅在 GenStruct<M>
确实实现了 Return
.[=16 时适用=]
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
// actually implement `Return` for GenStruct<M: Marker>,
// but compiler don't recognize that
impl Return for GenStruct<i32> {}
impl Return for GenStruct<u32> {}
为什么您认为要为任何 GenStruct<M: Marker>
实施 Return
?这仅针对两个特定变体实现它。实现特征的类型不是封闭集;任何人都可以在未来添加新的特性实现。 Rust 设计者不想让下游 crate 的变化影响你的 crate 的编译——那是疯了!
impl<M: Marker> Return for GenStruct<M> {
fn ret() {
if M::is_i32() { } else { }
}
}
这是正确的表述方式“对于每个实现了 Marker
的 M
,GenStruct<M>
实现了 Return
。某人如何或在哪里实现并不重要特征,因为保证有一个实现。
I cannot write a specialized implementation
没错,暂时。有一个正在进行的 RFC,RFC 1020: impl specialization 旨在允许在这些情况下进行专业化。
这是显示我的问题的抽象示例,提取自我重构一些 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>`
|
编译器没有识别出我实际上为每个 GenStruct<M>
实现了 Return
,其中 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 })
}
}
但是,如果我使用特征对象,我无法为 GenStruct<i32>
和 GenStruct<u32>
.
Return
的专门实现
编译器是否能够识别出我实现了 GenStruct<M: Marker>
或者我的代码不是惯用的 Rust?如果我的代码不符合地道,那么正确的写法是什么?
使用 where
子句,我们可以在泛型 impl
上添加额外的约束,这样它仅在 GenStruct<M>
确实实现了 Return
.[=16 时适用=]
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
// actually implement `Return` for GenStruct<M: Marker>, // but compiler don't recognize that impl Return for GenStruct<i32> {} impl Return for GenStruct<u32> {}
为什么您认为要为任何 GenStruct<M: Marker>
实施 Return
?这仅针对两个特定变体实现它。实现特征的类型不是封闭集;任何人都可以在未来添加新的特性实现。 Rust 设计者不想让下游 crate 的变化影响你的 crate 的编译——那是疯了!
impl<M: Marker> Return for GenStruct<M> { fn ret() { if M::is_i32() { } else { } } }
这是正确的表述方式“对于每个实现了 Marker
的 M
,GenStruct<M>
实现了 Return
。某人如何或在哪里实现并不重要特征,因为保证有一个实现。
I cannot write a specialized implementation
没错,暂时。有一个正在进行的 RFC,RFC 1020: impl specialization 旨在允许在这些情况下进行专业化。