While learning Rust, I stumbled upon the following scenario.
Consider this example:
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);
}
}
This does not compile:
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 | | }
| |_^
The way to fix this is to explicitly define the type constraint when implementing Drop
:
impl<T> Drop for Foo<T>
where
T: Debug,
{
fn drop(&mut self) {
println!("Dropping Foo with data: '{:?}'!", self.data);
}
}
However, I end up with the same constraint on multiple places, which does not make much sense to me.
Defining the constraint at struct declaration level should be enough, and the compiler should assume that T
is always going to implement Debug
, because there's simply no way that we can initialize Foo
without a T: Debug
Why is this explicitness required? Is this intentional or is this a current compiler limitation?