【问题标题】:Trait Bound is not satisfied for Result<(), Box<(dyn SomeTrait + 'static)>>Result<(), Box<(dyn SomeTrait + 'static)>> 不满足 Trait Bound
【发布时间】:2021-12-04 02:44:37
【问题描述】:
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();
}

我收到此错误,不知道如何解释或修复它。

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`

一个简单的解决方法是只使用if let Err() = GLOBAL_THING.set() {panic!(...)} 而不是使用unwrap(),但我想了解这里发生了什么并尽可能修复。

【问题讨论】:

    标签: rust traits abstraction dynamic-dispatch


    【解决方案1】:

    如果您查看unwrap method 文档,您会发现它不是为所有Results 定义的,而是只为E: Debug 定义的:

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

    它需要错误类型E来实现Debug,以便在解包失败时打印错误。

    错误信息显示结果类型为Result&lt;(), Box&lt;(dyn SomeTrait + 'static)&gt;&gt;,所以E = Box&lt;(dyn SomeTrait + 'static)&gt;。您可以通过使用SomeTrait: Debug 使此错误类型可调试,这要求实现SomeTrait 的任何类型也必须实现Debug

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

    一旦你这样做,你会遇到下一个错误:

    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`
    

    要解决此问题,您还需要创建盒装特征对象Send + Sync,以便它可以跨线程共享。

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

    你可以在Playground看到最终结果。

    【讨论】:

    • 谢谢,约翰!如果您好奇,实际的 Trait 称为 TimestampGenerator,它只是系统时间戳的包装器,但我在测试期间使用了 MockTimestampGenerator,我可以手动推进(1000)。我曾尝试在结构上派生 Debug,但没有意识到我需要: Debug on the trait。我在使用lazy_static时已经有了Send + Sync。
    • 无论如何,你摇滚。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多