Size: a a a

Rust — русскоговорящее сообществo

2020 September 09

L

Lev in Rust — русскоговорящее сообществo
Lev
У меня есть свой тип ошибки и для него реализован трейт From<T: std::error::Error>, а я хочу еще реализовать From<std::option::NoneError>, но когда я реализую напрямую, то получается ошибка:
error[E0119]: conflicting implementations of trait `std::convert::From<std::option::NoneError>` for type `error::MyError`:
 --> src/error.rs:44:1
  |
38 | impl<T: std::error::Error> From<T> for MyError {
  | ---------------------------------------------- first implementation here
...
44 | impl From<std::option::NoneError> for MyError {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `error::MyError`
  |
  = note: upstream crates may add a new impl of trait `std::error::Error` for type `std::option::NoneError` in future versions

(хотя на самом деле трейт Error не реализован для NoneError)
Как исправить эту ошибку?
Ну и еще вопрос: почему там conflicting implementations, если NoneError на самом деле не Error?
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
Lev
Ну и еще вопрос: почему там conflicting implementations, если NoneError на самом деле не Error?
Потому что NoneError может стать Error в будущих версиях, и это не будет ломающим изменением.
источник

L

Lev in Rust — русскоговорящее сообществo
Emmanuel Goldstein
Потому что легко может появиться два способа, в которых преобразование из Option к ошибке сигнализирует о разных ошибках
Ну мне вообще-то нужно преобразовывать NoneError в случаях, в которых вообще-то не должно быть так как там Some, но я не хочу делать unwrap на всякий случай
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
opt.unwrap_or_err(Error::new(...))
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
Или opt.unwrap_or_err(Error::Variant(...))
источник

L

Lev in Rust — русскоговорящее сообществo
Emmanuel Goldstein
Потому что NoneError может стать Error в будущих версиях, и это не будет ломающим изменением.
А есть какой-то способ пока все-таки сделать NoneError Error-ом либо реализовать From<...>?
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
Lev
А есть какой-то способ пока все-таки сделать NoneError Error-ом либо реализовать From<...>?
Нет. Первому мешает orphan rule, второму мешает то, что stdlib имеет право реализовать Error для NoneError без смены мажорной версии
источник

L

Lev in Rust — русскоговорящее сообществo
Обидно, но ладно, спасибо
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
Можешь сделать трейт-расширение и кастомный метод, если очень хочешь
источник

Ct

Casual tears in Rust — русскоговорящее сообществo
Интересно почему таки нету impl Error for NoneError в std
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
trait OptionExt {
   fn to_my_error(self) -> MyError;
}

impl <T>OptionExt for Option<T> { ... }
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
Casual tears
Интересно почему таки нету impl Error for NoneError в std
https://internals.rust-lang.org/t/should-noneerror-implement-the-error-trait/6312/4
TLDR: Потому что неочевидно, что должно быть в описании такой ошибки, и её может быть трудно дебажить.
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
Вместо этого можно использовать .ok_or()
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
Само существование NoneError это кривота, возникшая из попытки открепить ? от Result
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
None: Try — не естественная реализация, требующая привлечения отдельного типа
источник

Ct

Casual tears in Rust — русскоговорящее сообществo
Emmanuel Goldstein
Вместо этого можно использовать .ok_or()
Такое себе решение конечно. Кажется, специализация должна вопрос выше решить по-нормальному.
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
Специализация здесь упростит неверное решение проблемы.
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
.ok_or() — православный путь
источник

EG

Emmanuel Goldstein in Rust — русскоговорящее сообществo
В None не содержится достаточно информации, чтобы однозначно реализовывать From
источник
2020 September 10

К

Кирилл in Rust — русскоговорящее сообществo
Эрик
Вот так вот раст и заставляет людей писать быстрый код без dynamic dispatch.
Ну, если мне нужны различные поведения, под общим интерфейсом, с возможностью замены реализации в рантайме, то без dyamic dispatch, насколько я знаю, не обойтись. Или в раст завезли какую-то магию, о которой я не знаю?
источник