简体   繁体   中英

Why does the Rust compiler not convert from a library error to my error using the From trait?

Given this crate referencing an error from another crate, I would normally write a From implementation to convert types.

use xladd::variant::{Variant, XLAddError};
use failure::Fail;
use std::convert::TryInto;
use std::convert::From;
use std::error::Error;

#[derive(Debug, Fail)]
enum AARCError {
    #[fail(display = "F64 Conversion failure")]
    ExcelF64ConversionError,
    #[fail(display = "Bool Conversion failure")]
    ExcelBoolConversionError,
    #[fail(display = "Conversion failure")]
    ExcelStrConversionError,
}

impl From<XLAddError> for AARCError {
    fn from(err: XLAddError) -> Self {
        AARCError::ExcelF64ConversionError // Test for now
    }
}

pub fn normalize(array: Variant, min: Variant, max: Variant, scale: Variant) -> Result<Variant, AARCError> {
    let min: f64 = min.try_into().map_err(|e| AARCError::from(e))?;
    Ok(Variant::from_str("foo"))
}

But in this case I get an error:

error[E0277]: the trait bound `basic_stats::AARCError: std::convert::From<!>` is not satisfied
  --> src\basic_stats.rs:24:48
   |
24 |     let min: f64 = min.try_into().map_err(|e| AARCError::from(e))?;
   |                                               ^^^^^^^^^^^^^^^ the trait `std::convert::From<!>` is not implemented for `basic_stats::AARCError`
   |
   = help: the following implementations were found:
             <basic_stats::AARCError as std::convert::From<xladd::variant::XLAddError>>
   = note: required by `std::convert::From::from`

I don't understand what the From<!> trait is and trying to implement something like that gives an error for unnamed types.

What should I be doing to enable Rust to convert the external crate's errors to my ones?

I don't understand what the From<!> trait is and trying to implement something like that gives an error for unnamed types.

! is the "never" or uninhabited type; the type that has no possible values.

If a Result has ! for its error type, that means the operation cannot fail. It is impossible to convert from it to some other error type, because an error value cannot exist in the first place.

The never type is currently an experimental feature, requiring a nightly build of Rust. As such, it likely has a few rough edges, and it isn't as ergonomic as it could be. For example, I would expect the final feature to provide a blanket From<T> implementation for all types that implement TryFrom<T> with associated type Error = ! . It should be made easy to not have to handle the error that can't happen.

To fix your immediate problem, you can map that error to unreachable!() . The only issue with that approach is forwards-compatibility - if the third party crate later introduces a reachable error then your code would have an unhandled error, and no compile-time error to protect you. That's probably a part of why ! is not yet stabilised.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM