为什么Rust停止检测死结构,如果它们实现/派生一些trait?

20jt8wwn  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(160)

在正常情况下,如果一个结构体死亡,Rust会生成如下警告:

struct `Foo` is never constructed

字符串
这是很好的检测未使用的类型,可以删除。
然而,我注意到编译器会在结构体实现或派生出某个trait后立即停止对死结构体的警告。例如,对于一个纯粹由以下内容组成的源文件:

struct DeadStruct1;

#[derive(Clone)]
struct DeadStruct2;


编译器只会检测到DeadStruct1未被使用,而不会检测到DeadStruct2,显然在这个程序中也没有使用DeadStruct2(例如Rust Playground):

warning: struct `DeadStruct1` is never constructed
 --> src/lib.rs:1:8
  |
1 | struct DeadStruct1;
  |        ^^^^^^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default


我想知道为什么这个lint依赖于结构是否实现了trait?

quhf5bfb

quhf5bfb1#

这是因为一个已知的bug,它被讨论herehere
但是...这很奇怪
我测试了2018年至2023年间每年1月1日的版本,随着时间的推移,问题变得越来越严重。

  • 你提到的问题(#[derive(Clone)]PartialEqDefault;但不适用于DebugHash,如果trait是手动实现的,也不存在)在2018-01-01中已经存在。但在这一点上,只有派生实现导致了它,手动实现仍然有警告。
  • 2019-01-01中,似乎没有什么变化。
  • 但随后,通过2020-01-01,其他一些情况也停止产生警告。这段代码演示了行为(来自这篇文章,也在上面链接的讨论中):
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; }

字符串

  • 而且,当我们到达2021-01-01时,现在 * 任何 *(非毯子)trait实现都会使警告静音,无论是派生的还是手动的,都提到了Self

这似乎是我们今天的行为。

相关问题