如何对关联类型的关联类型施加类型约束(例如Iterator::Item)?

How to impose a type constraint on the associated type of an associated type (e.g. Iterator::Item)?

我正在尝试定义具有关联类型的特征。我还希望关联类型实现 Iterator,其 Item 关联类型实现 AsRef<str>.

虽然我知道如何针对函数或具体的 Iterator::Item 类型执行此操作,但我无法针对原始案例提出清晰简洁的解决方案。

多亏了有用的错误信息,我的编译解决方案是:

trait Note
where
    <<Self as Note>::FieldsIter as Iterator>::Item: AsRef<str>,
{
    type FieldsIter: Iterator;
    //other fields and methods omitted
}

丑陋的 where 子句让我觉得应该有更好的方法。

这无法编译,因为 Item: AsRef<str> 是非法构造:

trait Note {
    type FieldsIter: Iterator<Item: AsRef<str>>;
    //other fields and methods omitted
}

这失败了,因为这里不允许 impl:

trait Note {
    type FieldsIter: Iterator<Item = impl AsRef<str>>;
    //other fields and methods omitted
}

这不会编译,因为我希望 Iterator::Item 实现某个特征,而不是具体类型。

trait Note {
    type FieldsIter: Iterator<Item = AsRef<str>>;
    //other fields and methods omitted
}

您可以做一点小改进,但除此之外,当前的语法如您所见:

trait Note
where
    <Self::FieldsIter as Iterator>::Item: AsRef<str>,
{
    type FieldsIter: Iterator;
}

这是消歧语法,唯一的问题是还没有办法制作歧义版本! Rust issue #38078 已开放以允许使用 Foo::Bar::Baz 语法。

RFC 2289 也作为一种改进方式开放。实施 RFC 后,您的第二个示例应该可以工作:

trait Note {
    type FieldsIter: Iterator<Item: AsRef<str>>;
}

您现在可以解决此问题的一种方法类似于 IntoIterator。这就引入了另一种关联类型:

trait Note {
    type FieldsIter: Iterator<Item = Self::Item>;
    type Item: AsRef<str>;
}

我不喜欢这个,因为它引入的类型起初看起来彼此正交,但最终却紧密相关。