我有一个容器类型C<T>,其中包含类型的对象T。
struct C<T> {
insides: T
}
Run Code Online (Sandbox Code Playgroud)
假设我有两种类型A,B可以使用From特征进行转换:
struct A { }
struct B { }
impl From<A> for B {
fn from(a: A) -> B {
B { }
}
}
Run Code Online (Sandbox Code Playgroud)
就我而言,很自然地,我应该能够使用此转换轻松地将其放置在需要的C<A>地方C<B>。From这可以通过扩展到容器类型来完成:
impl From<C<A>> for C<B> {
fn from(ca: C<A>) -> C<B> {
C { insides: B::from(ca.insides) }
}
}
fn foo(cb: C<B>) {}
fn main() {
let ca = C { insides: A {} };
foo(ca.into());
}
Run Code Online (Sandbox Code Playgroud)
到目前为止一切顺利,一切都按预期编译和工作。
但这是一种相当自然的模式,适用于任何一对可转换类型,而不仅仅是A和B。因此,人们可能需要一个全面的特征实现:
impl<T, U> From<C<T>> for C<U> where U: From<T> {
fn from(t: C<T>) -> C<U> {
C { insides: U::from(t.insides) }
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用:
error[E0119]: conflicting implementations of trait `std::convert::From<C<_>>` for type `C<_>`
--> src/main.rs:19:1
|
19 | impl<T, U> From<C<T>> for C<U> where U: From<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> From<T> for T;
For more information about this error, try `rustc --explain E0119`.
Run Code Online (Sandbox Code Playgroud)
我理解这个错误:对于任何X如果我们指定 impl forT=X,U=X我们会发生冲突,因为X: From<X>对于所有X. 但这是一个相当烦人的边缘情况。有办法解决这个问题吗?以某种方式指定一个绑定说法T != U,或者任何其他方式告诉 Rust 使用corefor中的任何总括实现T=U以及我的 impl 其余部分?
在每晚,您可以使用自动特征来做到这一点:
#![feature(auto_traits, negative_impls)]
auto trait NotSame {}
impl<T> !NotSame for (T, T) {}
struct C<T> {
insides: T,
}
impl<T, U> From<C<T>> for C<U>
where
U: From<T>,
(T, U): NotSame,
{
fn from(t: C<T>) -> C<U> {
C {
insides: U::from(t.insides),
}
}
}
Run Code Online (Sandbox Code Playgroud)
但请注意,它可能具有相同的专业化健全性漏洞(当与生命周期交互时) - 我对此不确定。
但请注意,这实际上是(ab)使用编译器错误 - 编译器不会分析和证明 impl 不重叠,而是这些功能没有完全实现,因此编译器不会检查一致性。这意味着您需要更多类型注释,也意味着您不能使用impl<T> From<C<T>> for C<T> {}in std,因为它与您的类型注释重叠:
#![feature(auto_traits, negative_impls)]
auto trait NotSame {}
// Need at least one negative impl
impl !NotSame for (i32, String) {}
#[derive(Debug)]
struct C<T> {
insides: T,
}
impl<T, U> From<C<T>> for C<U>
where
U: From<T>,
(T, U): NotSame,
{
fn from(t: C<T>) -> C<U> {
C {
insides: U::from(t.insides),
}
}
}
#[derive(Debug)]
struct A;
#[derive(Debug)]
struct B;
impl From<A> for B {
fn from(_: A) -> B { B }
}
fn main() {
let c: C<B> = C { insides: B };
dbg!(<C<B> as From<C<B>>>::from(c));
}
Run Code Online (Sandbox Code Playgroud)
不要在生产中使用它,特别是因为它可能随时被修复。
| 归档时间: |
|
| 查看次数: |
339 次 |
| 最近记录: |