我想避免为包含未实现给定自动特征的类型的复合类型取消实现给定自动特征。
我对任何不是的东西都具有这种自动特征
()
:
pub auto trait NotVoid {}
impl !NotVoid for () {}
我用它来缓解以下特征的实现冲突;
Maybe
特征,其作用与 Option
类似,但是静态的。
pub trait Maybe<T>
where
T: ?Sized {}
// This implementation conflicts with...
impl<T> Maybe<T> for T
where
T: ?Sized {}
// ...this one:
impl<T> Maybe<T> for ()
where
T: ?Sized {}
通过这样做:
pub trait Maybe<T>
where
T: ?Sized {}
impl<T> Maybe<T> for T
where
T: ?Sized {}
impl<T> Maybe<T> for ()
where
T: NotVoid + ?Sized {}
效果很好。但是,我发现这个问题,如果我有一个由
()
组成的复合类型,它不会实现 NotVoid
,即使它不是实际的 ()
。这对于 Sync
、Send
和 Copy
等自动特征来说是有意义的,但这不是我想要用我的 NotVoid
特征实现的目标。例如:
struct A
{
nothing: ()
}
A
没有实现 NotVoid
,因为它包含 ()
,即使它应该实现(根据我想要 NotVoid
做的事情)。我如何才能仅对 NotVoid
实现 ()
的负实现,而不对 A
和其他类似的复合类型实现?
你不想要自动特征。自动特征在生活中的真正目的是当其中一个字段没有实现自动特征时阻止实现。
您想要的是负实现,这相当于(以其完整形式)负边界。也就是说,您想要一个为所有事物实现的特征,但不是为所有事物实现()
,或者一种限制特征实现(界限)的方法,以便它不适用于某些类型(条件)。 负面实现确实以某种形式存在于 Rust 中,事实上它们经常与自动特征捆绑在一起(你会发现你的自动特征需要两个不稳定的特征:一个用于特征本身(
auto_traits
),另一个用于特征本身)其实现 (
negative_impls
))。然而,Rust 中实现的负实现会影响连贯性,但它们不允许重叠。也就是说,虽然您对
()
有一个负的 impl,这意味着您可以有两个 impl,一个用于所有其他类型,一个用于
NotVoid
,并且它们不会重叠(正如您所观察到的),但您不是允许使负和正 impl 重叠,就像不允许您使两个正 impl 重叠一样,并且如果你尝试,编译器会朝你大喊大叫。 事实上,您所要求的东西是负面实现和专业化的组合,这两个众所周知的难以实现的功能,多年来在它们的实现中都发现了健全性漏洞。所以不要指望它会很快发生。
它可能仍然比汽车特征的状态更好,因为当前的计划是永远不会稳定它们,因为它们对生态系统的影响。
总之,您正在做的事情可能很有趣,但请不要在您编写的任何生产代码中使用它。