【发布时间】:2018-10-07 03:14:36
【问题描述】:
我有两个特点:
trait Foo {}
trait Bar {}
struct FooImpl;
impl Foo for FooImpl {}
struct BarImpl;
impl Bar for BarImpl {}
还有我想转换成的第三种类型:
struct Baz;
trait IntoBaz {
fn into(self) -> Baz;
}
由于连贯性,我无法为这两个特征定义两个 impls 和 IntoBaz,因此我将其包装为一个:
struct FooWrapper<F>(F)
where
F: Sized;
impl<F: Foo + Sized> From<F> for FooWrapper<F> {
fn from(f: F) -> FooWrapper<F> {
FooWrapper(f)
}
}
impl<F: Foo + Sized> IntoBaz for FooWrapper<F> {
fn into(self) -> Baz {
Baz
}
}
而且我不包装另一个:
impl<B: Bar> IntoBaz for B {
fn into(self) -> Baz {
Baz
}
}
fn do_thing<B: IntoBaz>(b: &B) {}
fn main() {
do_thing(&BarImpl);
}
到目前为止一切顺利,但为什么这条线不起作用?
fn main() {
do_thing(&FooImpl);
}
动机
我正在尝试将io::Write 支持添加到具有fmt::Write 支持的库中,而不会引入重大更改。
最简单的方法是定义一些涵盖共享行为的内部 Write 特征,但一致性问题意味着我不能只将 From<io::Write> 实例写入内部特征。
我尝试包装 io::Write 实例,以使强制强制显式化,以便编译器优先考虑较短的路径并避免不连贯,但它不会使用 From 实例自动强制。
【问题讨论】:
-
错误表明
FooImpl没有实现Bar(这是IntoBaz的全面实现所必需的)。你不打算这样做吗:do_thing(&FooWrapper(FooImpl));? -
不,因为目标是让自动强制执行此操作 - 我不明白为什么,在这种情况下,它没有。
-
from()或into()不要只是被自动调用。您需要执行以下操作:do_thing(&FooWrapper::from(FooImpl)); -
获得用户定义的自动强制的唯一合理方法是在某些包装类型上实现
Deref,这将导致包装自动衰减为被包装类型。你可以看到full list of coercions in th Nomicon。 -
"
from()有时会被语言自动调用" — 它可能似乎适用于某些库,但这只是那些要求参数为 @987654344 的库@ 并显式调用.into(),就像do_thing的主体必须这样做一样。
标签: generics rust polymorphism implicit-conversion