У меня есть следующие определения:
struct MyCustomFactory;
trait Factory {
fn new<'a>(entity: &'a str) -> Arc<dyn Display + 'a>
where
Self: Sized;
}
impl Factory for MyCustomFactory {
fn new<'a>(entity: &'a str) -> Arc<dyn Display + 'a>
where
Self: Sized,
{
Arc::new(entity)
}
}
Проблема более высокого уровня:
Я пытаюсь создать глобальную c (и неизменяемую) карту строк для структур, которые реализовать трейт Factory
. Цель состоит в том, чтобы для любого элемента-значения карты я мог рассматривать его как Factory
, вызывать new
против него и, в свою очередь, получить что-то , которое (в данном случае) реализует Display
trait.
У меня есть следующее:
static ITEMS: Lazy<BTreeMap<&'static str, Arc<dyn Factory>>> =
Lazy::new(|| {
let mut map = BTreeMap::new();
let value = Arc::new(MyCustomFactory) as Arc<dyn Factory>;
map.insert("foo", value);
map
});
Компилятор жалуется на:
77 | / static ITEMS: Lazy<BTreeMap<&'static str, Arc<dyn Factory>>> =
78 | | Lazy::new(|| {
79 | | let map = BTreeMap::new();
80 | | let value = Arc::new(MyCustomFactory) as Arc<dyn Factory>;
... |
88 | | });
| |_______^ `(dyn Factory + 'static)` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `(dyn Factory + 'static)`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<(dyn Factory + 'static)>`
= note: required because of the requirements on the impl of `std::marker::Send` for `alloc::collections::btree::node::Root<&'static str, std::sync::Arc<(dyn Factory + 'static)>>`
= note: required because it appears within the type `std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>`
= note: required because of the requirements on the impl of `std::marker::Sync` for `once_cell::imp::OnceCell<std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>>`
= note: required because it appears within the type `once_cell::sync::OnceCell<std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>>`
= note: required because of the requirements on the impl of `std::marker::Sync` for `once_cell::sync::Lazy<std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>>`
= note: shared static variables must have a type that implements `Sync`
Вещи, которые я пробовал:
Реализовать Sync
против признака : Объявление признака как имеющего trait Factory : Sync
(то есть все элементы, реализующие признак, должны реализовывать Sync
) и / или определение:
|
66 | unsafe impl Sync for dyn Factory {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
Обертывание Arc<dyn Factory>
: я пробовал использовать Mutex
/ RefCell
/ OnceCell
и другие, все приводило к той же ошибке . Похоже, должен быть способ рассматривать базовый MyCustomFactory
как синглтон, который можно заблокировать. Это нормально (и ожидается), что существует только один экземпляр этой структуры во всем мире.