【问题标题】:Why do I get a Rust compilation error when combining higher-rank trait bounds with associated types?为什么在将更高级别的特征边界与关联类型结合时会出现 Rust 编译错误?
【发布时间】:2020-02-18 15:15:11
【问题描述】:

我正在编写一些涉及通用特征和非'static 类型的Rust 代码,因此我遇到了近似generic associated types 的需要。我知道在当前的 Rust 中无法优雅地模拟 GAT,但我认为我已经找到了一种(不优雅的)解决方法,可以使用具有生命周期参数和更高级别特征边界的特征来适应我的特定情况。但是,我收到了我不理解的编译器错误,涉及关联类型的缺失特征实现。

以下代码显示了重现错误的最小示例。

use std::fmt::Debug;

trait Resource<'r> {
    type Value;
}

struct ResourceImpl();

impl<'r> Resource<'r> for ResourceImpl {
    type Value = u32;
}

fn test_generic<R>()
where
    for<'r> R: Resource<'r>,
    for<'r> <R as Resource<'r>>::Value: Debug,
{
}

fn test_specific() {
    test_generic::<ResourceImpl>();
}

当我尝试编译此代码 (rustc 1.41.0) 时,我收到以下错误消息。

error[E0277]: `<ResourceImpl as Resource<'r>>::Value` doesn't implement `std::fmt::Debug`
  --> src/lib.rs:21:5
   |
13 | fn test_generic<R>()
   |    ------------
...
16 |     for<'r> <R as Resource<'r>>::Value: Debug,
   |                                         ----- required by this bound in `test_generic`
...
21 |     test_generic::<ResourceImpl>();
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<ResourceImpl as Resource<'r>>::Value` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
   |
   = help: the trait `for<'r> std::fmt::Debug` is not implemented for `<ResourceImpl as Resource<'r>>::Value`

错误消息听起来像是在说u32 没有实现Debug,这没有任何意义。我一定是误解了错误消息的含义,但我无法弄清楚实际问题是什么。

【问题讨论】:

标签: rust


【解决方案1】:

有一个关于这个问题的open issue。

在您的情况下,解决方法可能是将Debug 绑定到关联类型Resource::Value?

trait Resource<'r> {
    type Value: Debug;
}.

【讨论】:

    【解决方案2】:

    正如 attdona 所指出的,这似乎是一个编译器错误(有一个未解决的问题 here)。关于该问题的讨论指向this Stack Overflow question,它提供了一个对我有用的解决方法。解决方法的关键点是,在更高级别的 trait bound 中提到的 trait 必须具有与 for&lt;_&gt; 内的参数匹配的生命周期参数。这可以通过创建具有所需生命周期参数的包装器特征(在本例中为 Debug)来实现。

    对于问题中给出的最小示例,解决方法如下所示:

    use std::fmt::Debug;
    
    trait Resource<'r> {
        type Value;
    }
    
    struct ResourceImpl();
    
    impl<'r> Resource<'r> for ResourceImpl {
        type Value = u32;
    }
    
    trait DebugWithLifetime<'r>: Debug {}
    
    impl<'r, T> DebugWithLifetime<'r> for T where T: Debug {}
    
    fn test_generic<R>()
    where
        for<'r> R: Resource<'r>,
        for<'r> <R as Resource<'r>>::Value: DebugWithLifetime<'r>,
    {
    }
    
    fn test_specific() {
        test_generic::<ResourceImpl>();
    }
    

    【讨论】:

      猜你喜欢
      • 2020-08-17
      • 2020-03-31
      • 1970-01-01
      • 1970-01-01
      • 2022-11-23
      • 2022-11-18
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多