简体   繁体   中英

Trait Bound is not satisfied for Result<(), Box<(dyn SomeTrait + 'static)>>

use once_cell::sync::OnceCell;

pub trait SomeTrait {}
pub struct Impl1 {}

impl SomeTrait for Impl1 {}

pub static GLOBAL_THING: OnceCell<Box<dyn SomeTrait>> = OnceCell::new();

pub fn main() {
    GLOBAL_THING.set(Box::new(Impl1 {})).unwrap();
}

I'm getting this error and not sure how to interpret it's meaning or fix it.

error[E0599]: the method `unwrap` exists for enum `Result<(), Box<(dyn SomeTrait + 'static)>>`, but its trait bounds were not satisfied
   --> src/main.rs:11:42
    |
11  |       GLOBAL_THING.set(Box::new(Impl1 {})).unwrap();
    |                                            ^^^^^^ method cannot be called on `Result<(), Box<(dyn SomeTrait + 'static)>>` due to unsatisfied trait bounds
    |
    = note: the following trait bounds were not satisfied:
            `Box<dyn SomeTrait>: Debug`

An easy workaround is to just do if let Err() = GLOBAL_THING.set() {panic!(...)} instead of using unwrap() , but I'd like to understand what's going on here and fix if possible.

If you take a look at the unwrap method documentation you'll see that it's not defined for all Result s, but only ones where E: Debug :

impl<T, E> Result<T, E>
where
    E: Debug, 
{
    pub fn unwrap(self) -> T;
}

It needs the error type E to implement Debug so that the error can be printed if unwrapping fails.

The error message shows that the result type is Result<(), Box<(dyn SomeTrait + 'static)>> , so E = Box<(dyn SomeTrait + 'static)> . You can make this error type debuggable by having SomeTrait: Debug , which requires that any type that implements SomeTrait must also implement Debug .

pub trait SomeTrait: Debug {}

#[derive(Debug)]
pub struct Impl1 {}

Once you do this you'll hit the next error:

error[E0277]: `dyn SomeTrait` cannot be shared between threads safely
  --> src/main.rs:11:1
   |
11 | pub static GLOBAL_THING: OnceCell<Box<dyn SomeTrait>> = OnceCell::new();
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn SomeTrait` cannot be shared between threads safely
   |
   = help: the trait `Sync` is not implemented for `dyn SomeTrait`
   = note: required because of the requirements on the impl of `Sync` for `Unique<dyn SomeTrait>`
   = note: required because it appears within the type `Box<dyn SomeTrait>`
   = note: required because of the requirements on the impl of `Sync` for `once_cell::imp::OnceCell<Box<dyn SomeTrait>>`
   = note: required because it appears within the type `once_cell::sync::OnceCell<Box<dyn SomeTrait>>`
   = note: shared static variables must have a type that implements `Sync`

To fix this you'll also want to make the boxed trait object Send + Sync so that it can be shared across threads.

pub static GLOBAL_THING: OnceCell<Box<dyn SomeTrait + Send + Sync>> = OnceCell::new();

You can see the final result on the Playground .

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