为什么我不能在带有类型参数的特征上添加一个全面的实现? [英] Why can't I add a blanket impl on a trait with a type parameter?
问题描述
考虑这两个特征:
pub trait Foo {
fn new(arg: u32) -> Self;
}
pub trait Bar<P>: Foo {
fn with_parameter(arg: u32, parameter: P) -> Self;
}
我想添加一揽子实现:
impl<T: Bar<P>, P: Default> Foo for T {
fn new(arg: u32) -> Self {
Self::with_parameter(arg, P::default())
}
}
但我收到编译器错误:
error[E0207]: the type parameter `P` is not constrained by the impl trait, self type, or predicates
--> src/lib.rs:9:17
|
9 | impl<T: Bar<P>, P: Default> Foo for T {
| ^ unconstrained type parameter
我想我收到这个错误是因为我违反了特征一致性规则,但我不明白这会违反什么规则.为什么不允许这种模式?而且,更重要的是,我可以在不出错的情况下实现我想要的吗?
I think I get this error because I'm violating trait coherence rules, but I don't understand exactly what rule this would break. Why is this pattern not allowed? And, more importantly, can I achieve what I want without getting an error?
推荐答案
问题是单个类型可以为 P
的多个值实现 Bar
.如果您有一个结构 Baz
实现了 Bar
和 Bar
,那么哪种类型应该 Foo::new
用于 P
?
The problem is that a single type could implement Bar<P>
for multiple values of P
. If you had a struct Baz
that implemented Bar<i32>
and Bar<String>
, which type should Foo::new
use for P
?
唯一的解决方案是确保单个类型不能多次实现 Bar
(如果这不是您想要的,那么您的设计就有缺陷!).为此,我们必须用关联类型替换 P
类型参数.
The only solution is to ensure that a single type cannot implement Bar
more than once (if that's not what you want, then you have a flaw in your design!). To do so, we must replace the P
type parameter with an associated type.
pub trait Bar: Foo {
type Parameter;
fn with_parameter(arg: u32, parameter: Self::Parameter) -> Self;
}
impl<T> Foo for T
where
T: Bar,
T::Parameter: Default,
{
fn new(arg: u32) -> Self {
Self::with_parameter(arg, T::Parameter::default())
}
}
Bar
的实现如下所示:
struct Baz;
impl Bar for Baz {
type Parameter = i32;
fn with_parameter(arg: u32, parameter: Self::Parameter) -> Self {
unimplemented!()
}
}
另见:
这篇关于为什么我不能在带有类型参数的特征上添加一个全面的实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!