为什么在实现 trait 时需要重复泛型约束?

3
在学习Rust的过程中,我遇到了以下情况。
考虑以下示例:
use std::fmt::Debug;

struct Foo<T>
where
    T: Debug,
{
    data: T,
}

impl<T> Drop for Foo<T> {
    fn drop(&mut self) {
        println!("Dropping Foo with data: '{:?}'!", self.data);
    }
}

这段代码无法编译:

error[E0277]: `T` doesn't implement `std::fmt::Debug`
  --> src/lib.rs:10:9
   |
10 | impl<T> Drop for Foo<T> {
   |         ^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
   |
   = help: the trait `std::fmt::Debug` is not implemented for `T`
   = help: consider adding a `where T: std::fmt::Debug` bound
note: required by `Foo`
  --> src/lib.rs:3:1
   |
3  | / struct Foo<T>
4  | | where
5  | |     T: Debug,
6  | | {
7  | |     data: T,
8  | | }
   | |_^

解决这个问题的方法是在实现 Drop 时明确定义类型限制:
impl<T> Drop for Foo<T>
where
    T: Debug,
{
    fn drop(&mut self) {
        println!("Dropping Foo with data: '{:?}'!", self.data);
    }
}

然而,我最终在多个地方都得到了相同的约束条件,这对我来说没有太多意义。

在结构声明层面定义约束应该足够了,编译器应该假定 T 总是会实现 Debug,因为我们无法初始化 Foo 而不使用 T: Debug

为什么需要这种明确性?这是有意为之还是当前编译器的限制?


请参考为什么需要绑定T:'a才能存储引用&'a T,这是一个类似的简化案例。 - Shepmaster
1个回答

2
这里提到了“暗示边界” RFC 2089,一旦实施,就不需要进行重复操作。
对于T: Debug的情况,我不会在结构定义中加入该边界。

当你找到答案时,请搜索现有答案。这是识别重复项并避免在许多SO问答中重复信息的最佳方法。 - Shepmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接