[英]Requiring a trait bound on the associated type of an inherited trait
I have a trait Foo
inheriting from another trait Bar
.我有一个特征
Foo
继承自另一个特征Bar
。 Bar
has an associated type Baz
. Bar
有一个关联类型Baz
。 Foo
constrains Baz
such that Baz
must implement Hoge
. Foo
约束Baz
使得Baz
必须实现Hoge
。
trait Hoge {}
trait Bar {
type Baz;
}
trait Foo: Bar where Self::Baz: Hoge {}
However, when I define a generic function requiring the generic type T
to implement Foo
,但是,当我定义一个泛型 function 需要泛型类型
T
来实现Foo
时,
// [DESIRED CODE]
fn fizz<T: Foo>(buzz: T) {
// ...
}
rustc
complains with EO277
unless I constrain T
explicitly: rustc
抱怨EO277
除非我明确限制T
:
fn fizz<T: Foo>(buzz: T) where T::Baz: Hoge {
// ...
}
I do not understand why I need to do this.我不明白为什么我需要这样做。 I would like to be able to write
[DESIRED CODE]
.我希望能够编写
[DESIRED CODE]
。 What is the recommended way to do this?推荐的方法是什么?
Sadly (or not), you have to repeat the bounds. 可悲的是(或者不是),您必须重复边界。
Last year I opened a issue thinking that the type checker was being inconsistent. 去年,我提出了一个问题 ,认为类型检查器不一致。 The code is similar to yours.
该代码与您的代码相似。
@arielb1 closed the issue and said that this was the intended behavior and gave this explanation: @ arielb1解决了该问题,并说这是预期的行为,并给出了以下解释:
The thing is that we don't want too many bounds to be implicitly available for functions, as this can lead to fragility with distant changes causing functions to stop compiling.
事实是,我们不希望太多的边界隐式地用于函数,因为这会导致脆弱性以及遥远的更改,从而导致函数停止编译。 There are basically 3 kinds of bounds available to a function:
函数基本上有3种范围可用:
- bounds from explicit where-clauses - eg
T: B
when you have that clause.明确的where子句的边界-例如,当您拥有该子句时为
T: B
。 This includes the "semi-explicit"Sized
bound.这包括“半显式”
Sized
限制。- bounds from supertraits of explicit where-clauses - a where-clause adds bounds for its supertraits (as
trait B: A
, theT: B
bound adds aT: A
bound).显式where子句的超性的边界-where子句为其上等性添加边界(作为
trait B: A
,T: B
边界添加T: A
边界)。- bounds from the lifetime properties of arguments (outlives/implicator/implied bounds).
参数生存期属性的边界(生存期/隐含子/隐含边界)。 These are only lifetime bounds, and irrelevant for the current problem.
这些仅是生命周期的界限,与当前问题无关。 rust-lang/rfcs#1214 involved them a great deal.
rust-lang / rfcs#1214涉及了很多。
If your bound isn't in the list, you will have to add it explicitly if you want to use it.
如果绑定不在列表中,则要使用它必须显式添加。 I guess this should be a FAQ entry.
我想这应该是常见问题解答条目。
Today I opened an issue to request that this information to be added to the docs. 今天,我打开了一个问题 ,要求将此信息添加到文档中。
It is possible to work around this behaviour by using another associated type in Foo
since the compiler accepts implicit bounds when part of the associated type definition ( playground ):可以通过在
Foo
中使用另一个关联类型来解决此行为,因为当关联类型定义 ( playground ) 的一部分时,编译器接受隐式边界:
trait Foo: Bar<Baz = Self::HogeBaz> {
type HogeBaz: Hoge;
}
The new associated type can be hidden in a helper trait to avoid having to include it in every implementation.新的关联类型可以隐藏在辅助特性中,以避免必须在每个实现中都包含它。 Full example (with renaming for clarity) ( playground )
完整示例(为清楚起见重命名)( 游乐场)
trait Bound {
fn bound();
}
trait Trait {
type Type;
}
trait BoundedTypeHelper: Trait<Type = Self::BoundedType> {
type BoundedType: Bound;
}
impl<T> BoundedTypeHelper for T
where
T: Trait,
Self::Type: Bound,
{
type BoundedType = Self::Type;
}
trait UserTrait: BoundedTypeHelper {}
fn fizz<T: UserTrait>() {
T::Type::bound()
}
I am with you in thinking that the original where-based bound ought to be treated as part of the trait definition and applied implicitly.我同意你的看法,认为原始的基于 where 的界限应该被视为特征定义的一部分并隐式应用。 It feels very arbitrary that bounding associated types inline works but
where
clauses do not.绑定关联类型内联有效但
where
子句无效感觉非常随意。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.