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

flo*_*ero 6 traits type-constraints rust associated-types

我正在尝试定义具有关联类型的特征。我还希望关联类型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
}
Run Code Online (Sandbox Code Playgroud)

这个丑陋的where条款让我觉得应该有更好的方法。

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

trait Note {
    type FieldsIter: Iterator<Item: AsRef<str>>;
    //other fields and methods omitted
}
Run Code Online (Sandbox Code Playgroud)

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

trait Note {
    type FieldsIter: Iterator<Item = impl AsRef<str>>;
    //other fields and methods omitted
}
Run Code Online (Sandbox Code Playgroud)

这无法编译,因为我想Iterator::Item实现某个特征,而不是成为具体类型。

trait Note {
    type FieldsIter: Iterator<Item = AsRef<str>>;
    //other fields and methods omitted
}
Run Code Online (Sandbox Code Playgroud)

She*_*ter 7

您可以进行一点小小的改进,但除此之外,当前的语法正如您所发现的那样:

trait Note
where
    <Self::FieldsIter as Iterator>::Item: AsRef<str>,
{
    type FieldsIter: Iterator;
}
Run Code Online (Sandbox Code Playgroud)

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

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

trait Note {
    type FieldsIter: Iterator<Item: AsRef<str>>;
}
Run Code Online (Sandbox Code Playgroud)

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

trait Note {
    type FieldsIter: Iterator<Item = Self::Item>;
    type Item: AsRef<str>;
}
Run Code Online (Sandbox Code Playgroud)

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