2017-04-09 139 views
3

我試圖創建一個功能HashMap的值:如何用函數引用創建一個lazy_static HashMap作爲值?

#[macro_use] 
extern crate lazy_static; 

use std::collections::HashMap; 

lazy_static! { 
    static ref HASHES: HashMap<&'static str, &'static Fn([u8])> = { 
     let mut m = HashMap::new(); 
     m.insert("md5", &md5); 
     m 
    }; 
} 

fn md5(bytes: &[u8]) -> String { 
    String::default() 
} 

編譯器給我一個錯誤:

error[E0277]: the trait bound `std::ops::Fn([u8]) + 'static: std::marker::Sync` is not satisfied in `&'static std::ops::Fn([u8]) + 'static` 
    --> src/main.rs:6:1 
    | 
6 | lazy_static! { 
    | _^ starting here... 
7 | |  static ref HASHES: HashMap<&'static str, &'static Fn([u8])> = { 
8 | |   let mut m = HashMap::new(); 
9 | |   m.insert("md5", &md5); 
10 | |   m 
11 | |  }; 
12 | | } 
    | |_^ ...ending here: within `&'static std::ops::Fn([u8]) + 'static`, the trait `std::marker::Sync` is not implemented for `std::ops::Fn([u8]) + 'static` 
    | 
    = note: `std::ops::Fn([u8]) + 'static` cannot be shared between threads safely 
    = note: required because it appears within the type `&'static std::ops::Fn([u8]) + 'static` 
    = note: required because of the requirements on the impl of `std::marker::Sync` for `std::collections::hash::table::RawTable<&'static str, &'static std::ops::Fn([u8]) + 'static>` 
    = note: required because it appears within the type `std::collections::HashMap<&'static str, &'static std::ops::Fn([u8]) + 'static>` 
    = note: required by `lazy_static::lazy::Lazy` 
    = note: this error originates in a macro outside of the current crate 

我不明白,我應該做些什麼來解決這個錯誤,我不知道任何其他方式創建這樣的HashMap

回答

6

您的代碼有多個問題。由編譯器給出的錯誤是告訴你,你的代碼,可以讓內存不安全:

`std::ops::Fn([u8]) + 'static` cannot be shared between threads safely 

你是存儲在您的HashMap的類型沒有保證它可以共享。

您可以通過將您的值類型更改爲&'static (Fn([u8]) + Sync)來指定此類邊界來「修復」。這解鎖下一個錯誤,由於你的函數簽名不匹配:

expected type `std::collections::HashMap<&'static str, &'static std::ops::Fn([u8]) + std::marker::Sync + 'static>` 
    found type `std::collections::HashMap<&str, &fn(&[u8]) -> std::string::String {md5}>` 

「修復」與&'static (Fn(&[u8]) -> String + Sync)導致深奧,kinded更高的壽命錯誤:

expected type `std::collections::HashMap<&'static str, &'static for<'r> std::ops::Fn(&'r [u8]) -> std::string::String + std::marker::Sync + 'static>` 
    found type `std::collections::HashMap<&str, &fn(&[u8]) -> std::string::String {md5}>` 

哪可以「固定」鑄造用&md5 as &'static (Fn(&[u8]) -> String + Sync))的功能,從而導致

note: borrowed value must be valid for the static lifetime... 
note: consider using a `let` binding to increase its lifetime 

這見底,因爲the reference you've made is to a temporary value that doesn't live outside of the scope


我把修復引入恐慌報價,因爲這不是真正的解決方案。正確的做法是隻用一個函數指針:

lazy_static! { 
    static ref HASHES: HashMap<&'static str, fn(&[u8]) -> String> = { 
     let mut m = HashMap::new(); 
     m.insert("md5", md5 as fn(&[u8]) -> std::string::String); 
     m 
    }; 
} 

老實說,我會說,一個HashMap可能是矯枉過正;我會使用一個數組。一小陣,可能比一個小HashMap更快:

type HashFn = fn(&[u8]) -> String; 

static HASHES: &'static [(&'static str, HashFn)] = &[ 
    ("md5", md5), 
]; 

您可以通過只通過列表迭代開始,也許是幻想和按字母順序排列,然後用binary_search當它變得有點大了。

相關問題