Как наложить ограничение типа на связанный тип ассоциированного типа (т.е. Iterator :: Item)? - PullRequest
0 голосов
/ 01 января 2019

Я пытаюсь определить черту со связанным типом.Я также хочу, чтобы связанный тип реализовал 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 голосов
/ 01 января 2019

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

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

Это недвусмысленный синтаксис, единственная проблема в том, что пока нет способасделать неоднозначную версию! Выпуск ржавчины # 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>;
}

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

...