Это сделано намеренно (вот историческая запись ), но есть вероятность, что ситуация может быть улучшена в будущем.и, по крайней мере, сообщение об ошибке следует переписать, чтобы объяснить, почему оно отказывается от компиляции.
Основная проблема заключается в том, что #[derive]
макросы должны "перенаправить" свои требования к свойствам во все поля структуры.Чтобы MyStruct
было Debug
, тип field
также должен быть Debug
.Рассмотрим это:
#[derive(Debug)] struct MyStruct<T: FromStr> {
field: T
}
Нам нужно сгенерировать impl<T: FromStr> Debug for MyStruct<T> where T:
Debug { ... }
(вы поймете, почему я выбрал FromStr
в секунду).Однако в этом случае:
#[derive(Debug)] struct MyStruct<T> {
field: T::Err
}
Здесь поле является ассоциированным типом, поэтому сгенерированный код действительно должен быть impl<T: FromStr> Debug for MyStruct<T> where T::Err:
Debug { ... }
.
Производные макросы фактически сканируют типы полей, чтобы увидетьнужно ли им связывать T
или связанный тип.Но если вы используете макрос типа, это ломается.Генерация кода не может видеть сквозь макрос, поэтому она не знает, какие границы генерировать.
Когда это было обнаружено, мы не могли решить, позволять ли макрос типа расширяться с нетерпением (кажется, что выможет попасть в цикл или проблемы с упорядочением), просто скопируйте макрос в предложение where
(производные обычно не делают этого, потому что он может расширяться до частного типа, вызывая ошибки типа в сгенерированном коде), или что-тоиначе , поэтому мы выполнили ошибку и сделали это ошибкой.
Проблема не может быть решена в действительности, подчиняясь «политике» получения: (1) она создает границы для вас,и (2) он только генерирует код, который компилируется.Но так как пользовательский производный стабильный, вы можете использовать такие ящики, как производная , которые позволяют обойти проблему, позволяя переписать границу: