从关联类型的切片中获取特性对象的切片。

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

Getting a slice of trait objects from a slice of an associated type

问题

我有两个相关的特性 `List`  `ListItem` ([playground 链接][1])
```rust
trait List {
    type Item: ListItem;
    fn items(&self) -> Vec<Self::Item>;
    /* 更多内容 */
}

其中 ItemList 上的关联类型,而 ListItem 对于 PartialEqDebug 有自定义实现。

在一个看起来像这样的 List 特性方法内:

fn foo(&self, other: &dyn List<Item=Self::Item>)

我想要比较项目的子切片,使用为 ListItem 定义的 PartialEq
例如:

let lhs: &[&dyn ListItem] = ...;
let rhs: &[&dyn ListItem] = ...;
assert_eq!(lhs, rhs);

但我无法将切片强制转换为正确的类型。

fn foo(&self, other: &dyn List<Item = Self::Item>) {
   let items = self.items();
   let items_slice: &[&dyn ListItem] = items.as_slice(); // <-- 这里有错误
error[E0308]: 不匹配的类型
   |
40 |         let these: &[&dyn ListItem] = these_items.as_slice();
   |                    ----------------   ^^^^^^^^^^^^^^^^^^^^^^ 期望类型为 `&[&dyn ListItem]`,找到类型为 `&[<Self as List>::Item]`
   |                    |
   |                    期望类型
   |
   = 注意:期望引用 `&[&dyn ListItem]`
              找到引用 `&[<Self as List>::Item]`
   = 帮助:考虑将关联类型 `<Self as List>::Item` 约束为 `&dyn ListItem`
   = 注意:更多信息请访问 https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

(playground 链接)

我该如何强制转换切片为正确的类型?


<details>
<summary>英文:</summary>

I have two related traits `List` and `ListItem` ([playground link][1]).
```rust
trait List {
    type Item: ListItem;
    fn items(&amp;self) -&gt; Vec&lt;Self::Item&gt;;
    /* more stuff */
}

where Item is an associated type on List and ListItem has a custom implementation for PartialEq and Debug

Inside of a List trait method that looks like

fn foo(&amp;self, other: &amp;dyn List&lt;Item=Self::Item&gt;)

I would like to compare sub-slices of the items, using the PartialEq defined for ListItem.
e.g.

let lhs: &amp;[&amp;dyn ListItem] = ...;
let rhs: &amp;[&amp;dyn ListItem] = ...;
assert_eq!(lhs, rhs);

but I cannot coerce the slices to the correct type.

fn foo(&amp;self, other: &amp;dyn List&lt;Item = Self::Item&gt;) {
   let items = self.items();
   let items_slice: &amp;[&amp;dyn ListItem] = items.as_slice(); // &lt;-- Error here
error[E0308]: mismatched types
   |
40 |         let these: &amp;[&amp;dyn ListItem] = these_items.as_slice();
   |                    ----------------   ^^^^^^^^^^^^^^^^^^^^^^ expected `&amp;[&amp;dyn ListItem]`, found `&amp;[&lt;Self as List&gt;::Item]`
   |                    |
   |                    expected due to this
   |
   = note: expected reference `&amp;[&amp;dyn ListItem]`
              found reference `&amp;[&lt;Self as List&gt;::Item]`
   = help: consider constraining the associated type `&lt;Self as List&gt;::Item` to `&amp;dyn ListItem`
   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

(playground link)

How can I coerce the slice to the correct type?

答案1

得分: 1

你不能。首先,你需要引用,而 items 包含拥有的项目。其次,你需要胖指针,而 items 具有具体的类型。

你需要将它们收集到一个 Vec 中:

let items = self.items();
let items_dyn = items
    .iter()
    .map(|item| item as &dyn ListItem)
    .collect::<Vec<_>>();
英文:

You cannot. First, you need references, and items contains owned items. Second, you need fat references, and items has concrete types.

You need to collect them into a Vec:

let items = self.items();
let items_dyn = items
    .iter()
    .map(|item| item as &amp;dyn ListItem)
    .collect::&lt;Vec&lt;_&gt;&gt;();

huangapple
  • 本文由 发表于 2023年6月26日 05:41:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76552517.html
匿名

发表评论

匿名网友

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

确定