generics - 为什么`From`不自动用于强制特征实现类型
问题描述
我有两个特点:
trait Foo {}
trait Bar {}
struct FooImpl;
impl Foo for FooImpl {}
struct BarImpl;
impl Bar for BarImpl {}
我想转换成的第三种类型:
struct Baz;
trait IntoBaz {
fn into(self) -> Baz;
}
由于连贯性,我无法为这两个特征定义两个impl
s 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
实例自动强制。
解决方案
查看错误信息:
error[E0277]: the trait bound `FooImpl: Bar` is not satisfied
--> src/main.rs:48:5
|
48 | do_thing(&FooImpl);
| ^^^^^^^^ the trait `Bar` is not implemented for `FooImpl`
|
= note: required because of the requirements on the impl of `IntoBaz` for `FooImpl`
note: required by `do_thing`
--> src/main.rs:45:1
|
45 | fn do_thing<B: IntoBaz>(b: &B) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
这就是说FooImpl
没有实现Bar
,这是您的全面IntoBaz for B
实现的要求。
FooWrapper
实现不相关,因为FooImpl
与FooWrapper
. From
和特征提供了一种在类型之间进行转换的Into
方法,但它不会自动发生。
您可能会尝试为可以转换为 的事物添加实现FooWrapper
,但这不起作用,因为实现可能重叠(并且专业化还不稳定)。
但是您可以IntoBaz
为 just 定义一个实现FooImpl
:
impl IntoBaz for FooImpl {
fn into(self) -> Baz {
IntoBaz::into(FooWrapper::from(self))
}
}
这将使您的代码编译:
fn main() {
do_thing(&BarImpl);
do_thing(&FooImpl);
}
推荐阅读
- caching - 这种 CDN/缓存模式的名称是什么,最省力的解决方案是什么?
- django - Django 羽毛笔编辑器 | 字段名称显示在 Django admin 中的羽毛笔编辑器小部件边框内
- php - Laravel 连接表
- java - 访问存储系统 Anylogic 中的特殊存储
- python - 突出显示 matplotlib 中的点序列
- facebook - Facebook 的客户匹配是否已弃用?
- html - 如何修复 For 循环(角度)中的输入?
- google-apps-script - Google 课堂 - 列出所有课程
- node.js - 使用 Google Cloud Vision 查找图像中特定类型的每个对象
- javascript - 矩阵(数组数组|二维数组)求和,没有循环。有更好的方法吗?