如何在关联类型(即Iterator :: Item)的关联类型上施加类型约束?

时间:2019-01-01 19:06:19

标签: rust traits type-constraints 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
}

丑陋的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
}

1 个答案:

答案 0 :(得分:2)

您可以进行一些小的改进,但是除此之外,当前的语法是您发现的:

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>;
}

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