gpt4 book ai didi

generics - 类型参数不受 impl 特征、自身类型或谓词的约束

转载 作者:行者123 更新时间:2023-12-05 02:25:36 24 4
gpt4 key购买 nike

我正在尝试为类型实现一个特征,这样对该类型的引用可以转换为一个迭代器,Item 实现了一个特定的特征

具体来说,考虑以下代码:

struct Arena;

pub trait Scan {
fn scan(&self, arena: &mut Arena);
}

impl<'a, 'b, Iterable, Item> Scan for Iterable
where
&'b Iterable: IntoIterator<Item = Item>,
Item: Scan + 'a,
{
fn scan(&self, arena: &mut Arena) {
for item in (&self).into_iter() {
item.scan(arena);
}
}
}

(See Playground 中的这个例子)

编译器提示,在 Item 下划线:

the type parameter `Item` is not constrained by the impl trait, self type, or predicates
unconstrained type parameter

我现在真的不明白我在哪里走错了方向:对我来说,看起来通用实现是否受到 where 条件的限制。我如何向编译器解释这个想法?

最佳答案

当你编写一个通用的特征实现时,例如

impl<'a, 'b, Iterable, Item> Scan for Iterable

要求所有泛型都出现在实现特征的类型的定义中。在您的情况下,Iterable 存在,但 Item 不存在。

但您并不真的需要 Item 是通用的。我认为您添加它只是为了在其上写一个约束。理想情况下你想写这样的东西:

impl<'a, 'b, Iterable> Scan for Iterable
where
&'b Iterable: IntoIterator<Item : Scan + 'a>,

不幸的是,这仍然是一个不稳定的功能 associated_type_bounds .

但幸运的是,您不需要为此绑定(bind)关联类型。你可以这样写:

impl<'a, 'b, Iterable> Scan for Iterable
where
&'b Iterable: IntoIterator,
<&'b Iterable as IntoIterator>::Item : Scan + 'a,

现在约束起作用了,但生命周期失效了!

error[E0309]: the parameter type `Iterable` may not live long enough
--> src/lib.rs:27:19
|
27 | &'b Iterable: IntoIterator,
| ^^^^^^^^^^^^ ...so that the reference type `&'b Iterable` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
23 | impl<'a, 'b, Iterable: 'b> Scan for Iterable
| ++++

如果您按照编译器的建议进行操作并添加 Iterable: 'b 并且...现在如果函数本身的实现失败:

error: lifetime may not live long enough
--> src/lib.rs:31:21
|
23 | impl<'a, 'b, Iterable> Scan for Iterable
| -- lifetime `'b` defined here
...
29 | fn scan(&self, arena: &mut Arena)
| - let's call the lifetime of this reference `'1`
30 | {
31 | for item in (&self).into_iter() {
| ^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'b`

这实际上是预期的,因为 &self 的匿名生命周期与 'b 无关,并且您无法更改它,因为您无法为函数的实现添加约束特质。

对此的明显解决方案(没有任何其他代码,也许它不适合你)是实现 &'b Iterable 的特征。这种方式 &self 实际上是 &&'b Iterable 并且所有的都适合在一起。此外,现在 Iterable: 'b 是隐式的,不再需要了:

impl<'a, 'b, Iterable> Scan for &'b Iterable
where
&'b Iterable: IntoIterator,
<&'b Iterable as IntoIterator>::Item : Scan + 'a,
{
fn scan(&self, arena: &mut Arena)
{
for item in self.into_iter() {
item.scan(arena);
}
}
}

顺便说一句,我认为 'a 生命周期几乎没有用。

关于generics - 类型参数不受 impl 特征、自身类型或谓词的约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74452724/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com