简体   繁体   中英

Trait bound T: From<Result<T, Error>> is not satisfied

I want to load nonce from a toml config file. nonce is retrieved in pub fn get_nonce() . I'd like to instantiate the result to salt of lazy_static macro type HarshBuilder .

use config::{Config, File, FileFormat, ConfigError};
use harsh::{Harsh, HarshBuilder};
use settings::Server;

const CFG_DEFAULT: &'static str = "conf/default";

lazy_static! {
    static ref MASK: Harsh = HarshBuilder::new()
        .length(7)
        .salt(get_nonce())
        .init()
        .expect("invalid harsh build");
}

fn conf_file() -> Config {
    let mut cfg = Config::default();
    cfg.merge(File::from_str(CFG_DEFAULT, FileFormat::Toml))
        .unwrap();

    cfg
}

pub fn get_nonce() -> Result<Vec<u8>, ConfigError> {
    let conf = conf_file();
    let search: Server = conf.get("server").unwrap();
    let nonce: Vec<u8> = search.nonce.into_bytes();

    Ok(nonce)
}

The compiler returns an error:

error[E0277]: the trait bound `std::vec::Vec<u8>: std::convert::From<std::result::Result<std::vec::Vec<u8>, config::ConfigError>>` is not satisfied
--> lib.rs:40:14
|
40 |     .salt(get_nonce())
|         ^^^^ the trait 
|
`std::convert::From<std::result::Result<std::vec::Vec<u8>, config::ConfigError>>` is not implemented for `std::vec::Vec<u8>`

|
= help: the following implementations were found:
         <std::vec::Vec<u8> as std::convert::From<std::ffi::CString>>
         <std::vec::Vec<u8> as std::convert::From<std::string::String>>
         <std::vec::Vec<T> as std::convert::From<&'a mut [T]>>
         <std::vec::Vec<T> as std::convert::From<std::borrow::Cow<'a, [T]>>>
       and 5 others
= note: required because of the requirements on the impl of `std::convert::Into<std::vec::Vec<u8>>` for `std::result::Result<std::vec::Vec<u8>, config::ConfigError>`

So get_nonce() returns an enum result of Result<String, ConfigError> . This does not appear to satisfy salt Option<Vec<u8>> . The attempt you see above is to convert Result enum to Vec<u8> . However, this does not fix the error.

Here is the HarshBuilder trait implementation for review:

/// Note that this factory will be consumed upon initialization.
#[derive(Debug, Default)]
pub struct HarshBuilder {
    salt: Option<Vec<u8>>,
    // ...ommitted for brevity
}

impl HarshBuilder {
/// Creates a new `HarshBuilder` instance.
pub fn new() -> HarshBuilder {
    HarshBuilder {
        salt: None,
        // ...ommited for brevity
    }
}

/// Note that this salt will be converted into a `[u8]` before use, meaning
/// that multi-byte utf8 character values should be avoided.
pub fn salt<T: Into<Vec<u8>>>(mut self, salt: T) -> HarshBuilder {
    self.salt = Some(salt.into());
    self
}

Trait bounds and lifetime elision is still a subject that I'm trying to wrap my head around. I can really use some guidance. Perhaps, this may be the reason as to why the answer is not completely obvious for me here.

Since your get_nonce function returns a Result , you need to handle the possible error. There are three ways you can fix your code here:

  • Given that get_nonce never returns an error, you can simply change it so that it returns nonce directly instead of Ok(nonce) .
  • Or you can call unwrap on the result to access the Vec<u8> that's inside (and crash if you later change get_nonce to generate errors).
  • Or you can add proper error handling all around (get rid of the unwrap s and use try! or the ? operator to propagate errors and catch them properly at some top-level point).

The Option<Vec<u8>> is a red herring, the important thing is the prototype of salt() , and as you can see in the definition of salt :

pub fn salt<T: Into<Vec<u8>>>(mut self, salt: T)

it expects an argument that satisfies the trait Into<Vec<u8>> . From the documentation you can see that there are these generic implementations of Into<T> :

  • From<T> for U implies Into<U> for T
  • Into is reflexive, which means that Into<T> for T is implemented.

So you may pass to salt either:

  • A value of type Vec<u8> .
  • A value of type T if there is such From<T> is implemented for Vec<u8> .
  • A value that implements Into<Vec<u8>> directly.

Now, you have a value of type Result<Vec<u8>, ConfigError> , that satisfies none of the above. And that is what all those error messages are trying to tell you.

The easy solution is to change your function into:

pub fn get_nonce() -> Vec<u8> {
     ....
     nonce
}

If you cannot change that return type you can use unwrap() to get the real value from a Result() (and crash on error):

    .length(7)
    .salt(get_nonce().unwrap())
    .init()

If the get_nonce() function can really fail, then you would have to manage the error properly, maybe making your MASK value of type Result<Harsh, ConfigError> ?

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