当前位置: 首页 > 知识库问答 >
问题:

要求将特征绑定在遗传特征的关联类型上

司空昊阳
2023-03-14

我有一个traitFoo从另一个traitBar继承。Bar有一个关联的类型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]。推荐的方法是什么?

共有2个答案

夏涵畅
2023-03-14

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

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

新的关联类型可以隐藏在帮助程序特征中,以避免必须将其包含在每个实现中。完整示例(为清楚起见,请重命名)(游乐场)

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的边界应该被视为特质定义的一部分,并隐式应用。内联绑定关联类型是可行的,但<code>和<code>子句不可行,这感觉非常随意。

令狐烨烨
2023-03-14

可悲的是(或者不是),你必须重复界限。

去年,我打开了一个问题,认为类型检查器不一致。代码与您的类似。

@arielb1关闭了该问题,并表示这是有意的行为,并给出了以下解释:

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

  • 来自显式 where 子句的约束 - 例如,当您有该子句时,T:B。这包括“半显式”大小绑定。
  • 来自显式 where 子句的超特征的边界 - 一个 where 子句为其超特征添加边界(作为特征 B:AT: B 边界添加一个 T:A 边界)。
  • 参数的生存期属性中的边界(超寿命/隐含边界/隐含边界)。这些只是生存期界限,与当前问题无关。rust-lang/rfcs#1214 让它们受益匪浅。

如果您的绑定不在列表中,则必须显式添加它才能使用它。我想这应该是一个常见问题解答条目。

今天,我打开了一个问题,要求将此信息添加到文档中。

 类似资料:
  • 我有一个特质,旨在加强对另一个特质的约束,例如: 如果我使用的是泛型而不是关联类型,我将能够告诉Rust < code > MyAssoc 在traits 和< code>B之间是相同的: 我如何对关联的类型做同样的事情?

  • 我希望有一个类型特征,对于任何在使用前不需要内存初始化的类型返回true,并且其复制构造函数可以作为memcpy实现。 我想让它回到真实 < li >整数类型(char、short int、int、long int等) < li >浮点数类型(float,double) < li>il::array (il::array是我自己对std::array的实现)for T是int、double、il:

  • 将跟踪和跨度添加到Slf4J MDC,以便您可以从日志聚合器中的给定跟踪或跨度中提取所有日志。示例日志: 2016-02-02 15:30:57.902 INFO [bar,6bfd228dc00d216b,6bfd228dc00d216b,false] 23030 --- [nio-8081-exec-3] ... 2016-02-02 15:30:58.372 ERROR [bar,6bfd

  • 反缓存 anticache设置该选项后,它将删除可能引起服务器响应的Header(if-none-match和if-modified-since)304 not modified。当您要确保完全捕获HTTP交换时,这很有用。当您要确保服务器以完整的数据响应时,也经常在客户端重播期间使用它。 客户端重播 客户端重播可以做到:您提供了一个以前保存的HTTP对话,而mitmproxy则一个接一个地重播了

  • 这个问题是在泛型关联类型在Rust中可用之前提出的,尽管它们是被提出和开发的。 我的理解是,特征泛型和关联类型在它们可以绑定到结构的类型数量上有所不同。 关联类型仅绑定1个类型: 泛型关联类型是这两种类型的混合。它们绑定到一个类型,正好有一个关联的生成器,而生成器又可以关联任何数量的类型。那么前面示例中的和这个泛型关联类型有什么区别呢?