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

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

Aliasing bounds on associated types of traits

问题

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

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

  1. trait Foo {
  2. type A;
  3. fn foo(&self, a: Self::A);
  4. }
  5. trait Alias: Foo
  6. where
  7. <Self as Foo>::A: From<u8>,
  8. {
  9. }
  10. impl<T> Alias for T
  11. where
  12. T: Foo,
  13. <T as Foo>::A: From<u8>,
  14. {
  15. }

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

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

编译器会报错:

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

这意味着我应该添加约束 &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:

  1. trait Foo {
  2. type A;
  3. fn foo(&amp;self, a: Self::A);
  4. }
  5. trait Alias: Foo
  6. where
  7. &lt;Self as Foo&gt;::A: From&lt;u8&gt;,
  8. {
  9. }
  10. impl&lt;T&gt; Alias for T
  11. where
  12. T: Foo,
  13. &lt;T as Foo&gt;::A: From&lt;u8&gt;,
  14. {
  15. }

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

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

the compiler complains:

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

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

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

  1. trait Alias: Foo {
  2. type AliasA: From<u8>;
  3. }
  4. impl<T> Alias for T
  5. where
  6. T: Foo,
  7. <T as Foo>::A: From<u8>,
  8. {
  9. type AliasA = T::A;
  10. }

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

英文:

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

  1. trait Alias: Foo {
  2. type AliasA: From&lt;u8&gt;;
  3. }
  4. impl&lt;T&gt; Alias for T
  5. where
  6. T: Foo,
  7. &lt;T as Foo&gt;::A: From&lt;u8&gt;,
  8. {
  9. type AliasA = T::A;
  10. }

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:

确定