Reputation: 26710
Under normal circumstances, Rust warns if a struct is dead by generating a warning like:
struct `Foo` is never constructed
This is nice to detect unused types that can be removed.
However, I noticed that the compiler stops warning about dead structs as soon as they implement or derive some trait. For instance, for a source file consisting purely of:
struct DeadStruct1;
#[derive(Clone)]
struct DeadStruct2;
The compiler will only detect that DeadStruct1
is unused, but not DeadStruct2
, which is obviously not used in this program either (example on Rust Playground):
warning: struct `DeadStruct1` is never constructed
--> src/lib.rs:1:8
|
1 | struct DeadStruct1;
| ^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
I'm wondering why this lint depends on whether or not a struct implements a trait?
Upvotes: 9
Views: 543
Reputation: 18619
It is because of a known bug, it is discussed here and here.
But... it's weird.
I tested the January 1st builds of each year between 2018 and 2023, and the problem got worse over time.
The problem you're mentioning (with #[derive(Clone)]
, and also for PartialEq
, Default
; but not for Debug
and Hash
, and also not if the trait was manually implemented) had already been there in 2018-01-01
. But at that point, only derived implementations caused it, manual implementations still had the warning.
In 2019-01-01
, nothing seems to have changed.
But then, by 2020-01-01
, some other cases stopped producing the warning too. This code demonstrates the behavior (from this post, also in the discussion linked above):
struct Foo;
// Does not prevent the warning
trait Bar0 {}
impl Bar0 for Foo {}
// Does not prevent the warning
trait Bar1 { fn dummy(); }
impl Bar1 for Foo { fn dummy () {} }
// Prevents the warning
trait Bar2 { fn dummy(&self); }
impl Bar2 for Foo { fn dummy (&self) {} }
// Prevents the warning
trait Bar3 { fn dummy() -> Self; }
impl Bar3 for Foo { fn dummy () -> Self { todo!() } }
// Prevents the warning
trait Bar4 { type Dummy; }
impl Bar4 for Foo { type Dummy = Self; }
// Prevents the warning
trait Bar5 { const DUMMY: Self; }
impl Bar5 for Foo { const DUMMY: Self = Self; }
And, as we arrive to 2021-01-01
, now any (non-blanket) trait implementation silences the warning, no matter if derived or manual, mentions Self
or not!
And this seems to be the behavior we have to this day.
Upvotes: 7