Как наложить ограничение типа на связанный тип связанного типа (например, 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
}

person flopacero    schedule 01.01.2019    source источник


Ответы (1)


Вы можете сделать одно небольшое улучшение, но в остальном текущий синтаксис для этого такой, как вы обнаружили:

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

Я не фанат этого, потому что он вводит типы, которые на первый взгляд кажутся ортогональными друг другу, но в конечном итоге тесно связаны.

person Shepmaster    schedule 01.01.2019