首页 > 解决方案 > 如何对关联类型的关联类型(例如 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
}

标签: rusttraitstype-constraintsassociated-types

解决方案


你可以做一个小的改进,但除此之外,当前的语法是你发现的:

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

这是消除歧义的语法,唯一的问题是还没有办法制作歧义的版本!Rust 问题 #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>;
}

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


推荐阅读