Trait bound T: From<Result<T, Error>> 不满足

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

我想从 toml 配置文件加载 noncenoncepub fn get_nonce() 中检索到。我想将结果实例化为 lazy_static 宏类型 HarshBuildersalt

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)
}

编译returns一个错误:

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>`

所以 get_nonce() returns Result<String, ConfigError> 的枚举结果。这似乎不满足 salt Option<Vec<u8>>。您在上面看到的尝试是将 Result 枚举转换为 Vec<u8>。但是,这不能修复错误。

这里是 HarshBuilder 特征实现以供审查:

/// 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
}

特质界限和生命周期省略仍然是我努力思考的主题。我真的可以使用一些指导。也许,这可能是为什么答案对我来说不是很明显的原因。

由于您的 get_nonce 函数 returns a Result,您需要处理可能的错误。您可以通过三种方式修复此处的代码:

  • 鉴于 get_nonce 从来没有 returns 错误,您可以简单地更改它,使其直接 returns nonce 而不是 Ok(nonce)
  • 或者您可以在结果上调用 unwrap 以访问内部的 Vec<u8>(如果稍后更改 get_nonce 会导致崩溃)。
  • 或者你可以在周围添加适当的错误处理(摆脱 unwraps 并使用 try!? 运算符传播错误并在某些顶部正确捕获它们-级点)。

Option<Vec<u8>>是一个转移注意力的问题,重要的是salt()的原型,正如你在salt的定义中看到的:

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

它需要一个满足特征 Into<Vec<u8>> 的参数。从 documentation 可以看出 Into<T>:

有这些通用实现
  • From<T>对于U意味着Into<U>对于T
  • Into是自反的,也就是说实现了Into<T> for T

因此您可以传递给 salt

  • Vec<u8> 类型的值。
  • T 类型的值(如果有 From<T> 是为 Vec<u8> 实现的。
  • 直接实现 Into<Vec<u8>> 的值。

现在,您有一个 Result<Vec<u8>, ConfigError> 类型的值,它满足上面的 none。这就是所有这些错误消息试图告诉您的内容。

简单的解决方案是将函数更改为:

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

如果您无法更改 return 类型,您可以使用 unwrap()Result() 中获取实际值(错误时崩溃):

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

如果 get_nonce() 函数真的会失败,那么您将不得不妥善处理错误,也许使您的 MASK 值成为 Result<Harsh, ConfigError> 类型?