关于特质关联类型的别名边界

huangapple go评论61阅读模式
英文:

Aliasing bounds on associated types of traits

问题

我试图为一组具有关联类型的特质创建一个类型别名。但是,我的别名实际上是相反的,即它要求在使用它的任何地方都满足约束条件。

类似于这种情况的最小化示例如下。我想要创建一个别名,用于特质 Foo,只要其类型 A 可以从 u8 创建:

trait Foo {
    type A;

    fn foo(&self, a: Self::A);
}

trait Alias: Foo
where
    <Self as Foo>::A: From<u8>,
{
}

impl<T> Alias for T
where
    T: Foo,
    <T as Foo>::A: From<u8>,
{
}

当我想要在函数 test 中使用此别名时:

fn test<T: Alias>(x: &T, y: u8) {
    x.foo(y.into());
}

编译器会报错:

error[E0277]: the trait bound `<T as Foo>::A: From<u8>` is not satisfied
  --> src/lib.rs:20:12
   |
20 | fn test<T: Alias>(x: &T, y: u8) {
   |            ^^^^^ the trait `From<u8>` is not implemented for `<T as Foo>::A`
   |
note: required by a bound in `Alias`
  --> src/lib.rs:9:23
   |
7  | trait Alias: Foo
   |       ----- required by a bound in this trait
8  | where
9  |     <Self as Foo>::A: From<u8>,
   |                       ^^^^^^^^ required by this bound in `Alias`
help: consider further restricting the associated type
   |
20 | fn test<T: Alias>(x: &T, y: u8) where <T as Foo>::A: From<u8> {
   |                                 +++++++++++++++++++++++++++++

这意味着我应该添加约束 &lt;T as Foo&gt;::A: From&lt;u8&gt;,但我想避免这样做。

我做错了什么?如果这是编译器的限制,有没有办法实现相同的行为?

英文:

I'm trying to make a type alias for a group of traits with associated types. However, my alias works in the opposite way, i.e., it requires the bounds to be satisfied wherever it's used.

A minimized example similar to the situation is as follows. I want to create an alias for the trait Foo whenever its type A can be created from a u8:

trait Foo {
    type A;

    fn foo(&amp;self, a: Self::A);
}

trait Alias: Foo
where
    &lt;Self as Foo&gt;::A: From&lt;u8&gt;,
{
}

impl&lt;T&gt; Alias for T
where
    T: Foo,
    &lt;T as Foo&gt;::A: From&lt;u8&gt;,
{
}

When I want to use this alias in the function `test:

fn test&lt;T: Alias&gt;(x: &amp;T, y: u8) {
    x.foo(y.into());
}

the compiler complains:

error[E0277]: the trait bound `&lt;T as Foo&gt;::A: From&lt;u8&gt;` is not satisfied
  --&gt; src/lib.rs:20:12
   |
20 | fn test&lt;T: Alias&gt;(x: &amp;T, y: u8) {
   |            ^^^^^ the trait `From&lt;u8&gt;` is not implemented for `&lt;T as Foo&gt;::A`
   |
note: required by a bound in `Alias`
  --&gt; src/lib.rs:9:23
   |
7  | trait Alias: Foo
   |       ----- required by a bound in this trait
8  | where
9  |     &lt;Self as Foo&gt;::A: From&lt;u8&gt;,
   |                       ^^^^^^^^ required by this bound in `Alias`
help: consider further restricting the associated type
   |
20 | fn test&lt;T: Alias&gt;(x: &amp;T, y: u8) where &lt;T as Foo&gt;::A: From&lt;u8&gt; {
   |                                 +++++++++++++++++++++++++++++

that means I should add the constraint &lt;T as Foo&gt;::A: From&lt;u8&gt; as well, which I want to avoid.

Which part I'm doing wrong? If it is a limitation in the compiler, is there any way to achieve the same behavior?

答案1

得分: 1

这在你也在新的特质中进行类型更改时有效。

trait Alias: Foo {
    type AliasA: From<u8>;
}

impl<T> Alias for T
where
    T: Foo,
    <T as Foo>::A: From<u8>,
{
    type AliasA = T::A;
}

然后只需将任何对 T::A 的使用替换为 T::AliasA

英文:

This works if you also make a type in the new trait.

trait Alias: Foo {
    type AliasA: From&lt;u8&gt;;
}

impl&lt;T&gt; Alias for T
where
    T: Foo,
    &lt;T as Foo&gt;::A: From&lt;u8&gt;,
{
    type AliasA = T::A;
}

Then just replace any usage of T::A with T::AliasA.

huangapple
  • 本文由 发表于 2023年5月30日 12:27:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76361626.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定