Rust中实现Kind泛型Error类型遇From trait冲突问题求助
问题分析
你遇到的错误根源在于Rust标准库中默认存在impl<T> From<T> for T这个通用实现,而你的impl<K2: Kind, K1: IntoKind<K2>> From<K1> for Error<K2>会和它产生潜在冲突:当K1恰好等于Error<K2>时,你的impl会和标准库的From<Error<K2>> for Error<K2>形成重叠。
你添加的!IntoKind<K1> for Error<K2>负实现确实禁止了Error<K2>实现IntoKind<K1>,但Rust的impl冲突检查是基于签名的静态分析,不会考虑你的K1: IntoKind<K2>约束是否和负实现矛盾。编译器只看到存在一种理论上的可能性(哪怕你用负实现堵死了这条路),所以会报错。
解决方案
方案1:给K1添加约束,排除Error类型
通过引入marker trait标记非Error类型,在impl中约束K1必须实现该marker,从而排除K1为Error的情况:
#![feature(negative_impls)] use std::fmt::{Debug, Display}; pub trait Kind: Debug + Display + Send + Sync + 'static {} pub trait IntoKind<K: Kind> { fn into_kind(self) -> K; } impl<K: Kind> IntoKind<K> for K { fn into_kind(self) -> K { self } } // 定义marker trait,标记非Error类型 pub trait NonErrorKind {} // 给所有Kind类型默认实现(Error<K>不是Kind,不会自动实现) impl<K: Kind> NonErrorKind for K {} // 负实现:Error<K>永远不是NonErrorKind impl<K: Kind> !NonErrorKind for Error<K> {} pub struct Error<K: Kind> { kind: K } impl<K> !Kind for Error<K> {} impl<K1: Kind, K2: Kind> !IntoKind<K1> for Error<K2> {} // 添加NonErrorKind约束,排除K1是Error的情况 impl<K2: Kind, K1: IntoKind<K2> + NonErrorKind> From<K1> for Error<K2> { fn from(kind: K1) -> Self { Error { kind: kind.into_kind() } } }
方案2:拆分impl,单独处理Error间的转换
把普通Kind类型的转换和Error类型间的转换分开实现,通过约束K1为Kind类型(Error
#![feature(negative_impls)] use std::fmt::{Debug, Display}; pub trait Kind: Debug + Display + Send + Sync + 'static {} pub trait IntoKind<K: Kind> { fn into_kind(self) -> K; } impl<K: Kind> IntoKind<K> for K { fn into_kind(self) -> K { self } } pub struct Error<K: Kind> { kind: K } impl<K> !Kind for Error<K> {} impl<K1: Kind, K2: Kind> !IntoKind<K1> for Error<K2> {} // 处理普通Kind类型到Error的转换 impl<K2: Kind, K1: Kind + IntoKind<K2>> From<K1> for Error<K2> { fn from(kind: K1) -> Self { Error { kind: kind.into_kind() } } } // 单独处理Error<K1>到Error<K2>的转换 impl<K2: Kind, K1: Kind + IntoKind<K2>> From<Error<K1>> for Error<K2> { fn from(err: Error<K1>) -> Self { Error { kind: err.kind.into_kind() } } }
方案3:放弃From trait,自定义转换方法
直接给Error<K>定义专属的转换方法,绕过From trait的冲突问题:
#![feature(negative_impls)] use std::fmt::{Debug, Display}; pub trait Kind: Debug + Display + Send + Sync + 'static {} pub trait IntoKind<K: Kind> { fn into_kind(self) -> K; } impl<K: Kind> IntoKind<K> for K { fn into_kind(self) -> K { self } } pub struct Error<K: Kind> { kind: K } impl<K> !Kind for Error<K> {} impl<K1: Kind, K2: Kind> !IntoKind<K1> for Error<K2> {} impl<K2: Kind> Error<K2> { pub fn from_kind<K1: IntoKind<K2>>(kind: K1) -> Self { Error { kind: kind.into_kind() } } }
内容的提问来源于stack exchange,提问作者WormholeX
相关产品推荐
相关产品推荐

