【问题标题】:Requiring a trait bound on the associated type of an inherited trait要求在继承特征的关联类型上绑定特征
【发布时间】:2021-10-01 00:18:00
【问题描述】:

我有一个特征 Foo 继承自另一个特征 BarBar 具有关联类型 BazFoo 约束 Baz 使得 Baz 必须实现 Hoge

trait Hoge {}

trait Bar {
    type Baz;
}

trait Foo: Bar where Self::Baz: Hoge {}

但是,当我定义一个需要泛型类型T 来实现Foo 的泛型函​​数时,

// [DESIRED CODE]
fn fizz<T: Foo>(buzz: T) {
    // ...
}

rustc 抱怨 EO277 除非我明确限制 T

fn fizz<T: Foo>(buzz: T) where T::Baz: Hoge {
    // ...
}

我不明白为什么我需要这样做。我希望能够写[DESIRED CODE]。推荐的方法是什么?

【问题讨论】:

  • 您知道trait Foo where ... 在概念上是否有效吗?我看到它编译,所以语法没问题,但它看起来……很奇怪。
  • 您可以想象我需要一些关联类型的行为 (Baz),这样当我在某些实现中使用 Foo 时,我可以使用该行为,类似于人们可能想要的要求继承特征的某些行为 (Bar)。
  • 对不起,我不清楚。你的 intent 是可以理解的(因为它可以使用像 Hoge 这样的元句法变量),我主要是问你是否见过 where 子句用于特征定义,而没有泛型类型;我不确定我有。
  • 我不确定我是否曾经有过。是否有其他方法可以实现我的意图?
  • @Shepmaster,嗯,有个泛型类型:Self,所有关联的类型本质上都是泛型类型参数,尤其是Self。虽然它确实看起来很奇怪;如果这是另一种在语法上允许但对编译器没有语义意义的东西,我不会感到惊讶(我肯定在 Rust 问题跟踪器上看到过类似的东西)。

标签: rust


【解决方案1】:

遗憾的是(或不是),您必须重复界限。

去年我打开了issue,认为类型检查器不一致。代码和你的类似。

@arielb1 关闭了这个问题,并表示这是预期的行为并给出了这样的解释:

问题是我们不希望隐含太多界限 可用于函数,因为这可能导致远距离的脆弱性 导致函数停止编译的更改。基本上有3个 函数可用的边界种类:

  • 来自显式 where 子句的界限 - 例如T: B 当你有那个子句时。这包括“半显式”Sized 绑定。
  • 显式 where 子句的超特征的边界 - where 子句为其超特征添加边界(如 trait B: AT: B 边界添加 T: A 绑定)。
  • 参数的生命周期属性的界限(寿命/暗示/隐含界限)。这些只是一生的界限, 并且与当前问题无关。 rust-lang/rfcs#1214参与 很多。

如果您的绑定不在列表中,您必须明确添加它 你想用它。我想这应该是一个常见问题条目。

今天我打开了issue 请求将此信息添加到文档中。

【讨论】:

  • 我明白了。我强烈不同意这种排除一些合理预期的行为的想法,因为这可能会使 Rust 开发变得更加困难。我们应该弄清楚用户想要输入什么,并尽最大努力与之匹配。
【解决方案2】:

可以通过在 Foo 中使用另一个关联类型来解决此问题,因为当关联类型定义 (playground) 的一部分时编译器接受隐式边界:

trait Foo: Bar<Baz = Self::HogeBaz> {
    type HogeBaz: Hoge;
}

新的关联类型可以隐藏在辅助特征中,以避免在每个实现中都包含它。完整示例(为清晰起见重命名) (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()
}

我和你一样认为,最初的 where-based bound 应该被视为 trait 定义的一部分并隐式应用。限制关联类型内联有效但 where 子句无效,这感觉非常随意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    • 2021-10-09
    • 2013-12-21
    相关资源
    最近更新 更多