如何在Rust中编写无冲突的泛型From trait实现?
问题
想要实现一个泛型类型A<T>,使其能从任何可转换为T的类型U通过From trait完成转换,编写的代码如下:
struct A<T> { value: T, } impl<T, U> From<U> for A<T> where U: Into<T> { fn from(value: U) -> Self { Self { value: value.into() } } }
但编译时出现冲突错误:
error[E0119]: conflicting implementations of trait `From<A<_>>` for type `A<_>` --> src/main.rs:5:1 | 5 | impl<T, U> From<U> for A<T> where U: Into<T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `core`: - impl<T> From<T> for T;
原因是当前实现过于宽泛,当U为A<_>时,会和标准库中From<T> for T的默认实现产生冲突。需要让该From实现仅在U不是A<_>类型时生效。
解决方案
可以借助负向 trait bound(Rust 1.51及以上版本支持)结合自定义辅助trait来实现需求:
struct A<T> { value: T, } // 自定义辅助trait,标记所有A<T>类型 trait IsA {} impl<T> IsA for A<T> {} impl<T, U> From<U> for A<T> where U: Into<T>, // 限制U不能是实现了IsA的类型(即排除所有A<T>) U: !IsA, { fn from(value: U) -> Self { Self { value: value.into() } } }
原理说明
- 自定义
IsAtrait并为所有A<T>实现该trait,以此标识A类型家族; - 在
From的实现约束中添加U: !IsA,告知编译器仅当U不属于A类型家族时,才使用当前实现; - 这样就避免了和标准库中
From<T> for T的实现产生冲突,当U为A<_>时,会匹配标准库的默认实现而非自定义实现。
如果需要额外支持A<T>到A<U>的转换(当T: Into<U>时),可以单独添加针对性实现:
impl<T, U> From<A<T>> for A<U> where T: Into<U> { fn from(value: A<T>) -> Self { Self { value: value.value.into() } } }
内容的提问来源于stack exchange,提问作者petersohn
相关产品推荐
相关产品推荐

