#rust
Вопрос:
Я хочу, чтобы мой тип MyError
был конвертируемым из всех других типов. Я попытался сделать это следующим образом:
impl<T> From<T> for MyError {
fn from(_: T) -> Self {
MyError::Unknown
}
}
Но я получаю следующую ошибку:
error[E0119]: conflicting implementations of trait `std::convert::From<MyError>` for type `MyError`
--> src/main.rs:26:5
|
26 | impl<T> From<T> for MyError {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> From<T> for T;
Это имеет смысл , потому что один такой T
обязательно MyError
, и эта реализация охватывается impl<T> From<T> for T
. В идеале я мог бы исключить MyError
из T
подобных:
impl<T> From<T> for MyError where T != MyError
но очевидно, что это не сработает. Есть ли какой-нибудь способ выполнить то, что я пытаюсь сделать?
Комментарии:
1. вы не можете этого сделать из-за пустой реализации.
2. Вы не можете этого сделать, так что, может быть, дайте нам дополнительную информацию о том, почему вы пытаетесь это сделать…
Ответ №1:
Учитывая именно то, что вы указали, вы можете достичь этого, используя auto_traits
функции «Только ночью» и negative_impls
«только ночью» следующим образом:
#![feature(auto_traits, negative_impls)]
enum MyError {
A,
B,
C,
Unknown,
}
auto trait IsNotMyError {}
impl !IsNotMyError for MyError {}
impl<T: IsNotMyError> From<T> for MyError {
fn from(_: T) -> Self {
Self::Unknown
}
}
Однако этот impl не очень полезен, для ?
чего , я полагаю, вы его используете.
Предполагая , что вы получаете a Result<T, E>
и хотите преобразовать E
его в MyError::Unknown
using ?
, это не сработает:
fn f<T, E>(f: impl FnOnce() -> Result<T, E>) -> Result<T, MyError> {
let value = f()?;
Ok(value)
}
Вы получите следующее сообщение об ошибке:
error[E0277]: the trait bound `E: IsNotMyError` is not satisfied
--> src/lib.rs:24:20
|
24 | let value = f()?;
| ^ the trait `IsNotMyError` is not implemented for `E`
Это потому E
, что может быть MyError
, и тогда неясно, должна ли ошибка возврата быть просто E
или MyError::Unknown
.
Вместо этого рекомендуется просто сделать .map_err(|_| MyError::Unknown)?
это, если вы хотите избавиться от ошибки, в отличие от ее реализации From<T>
:
fn f<T, E>(f: impl FnOnce() -> Result<T, E>) -> Result<T, MyError> {
let value = f().map_err(|_| MyError::Unknown)?;
Ok(value)
}
То есть, предполагая, что вы хотите удалить исходную ошибку, в противном случае просто оберните перечисление ошибок общим E
и передайте ошибку обратно.
Вы можете найти более подробную информацию о функциях, описанных выше, в разделе «Нестабильная книга«.:
Комментарии:
1. Я ценю подробное объяснение, спасибо!
2. Я был бы признателен за ссылку на источник, чтобы узнать больше об этих функциях.
3. @Stargateur Вы можете найти более подробную информацию о них в нестабильной книге : Автоматические черты и негативные последствия
4. мой плохой, я имею в виду в ответе, комментарий улетает