Description
In #74836 it was discovered that [foo; 0]
will leak foo
, causing observable effects if foo
has a destructor. In response #74857 was opened in order to warn users against using [foo; 0]
to construct a zero-length array in favor of []
, but this was deemed to be overkill.
However, since then some new information has emerged that I believe calls for re-evaluating this decision. The problem comes from the use of array-repeat expressions in constant contexts. Consider the following program, which works on stable Rust today:
struct Foo;
impl Drop for Foo {
fn drop(&mut self) {
println!("dropped!")
}
}
const FOO: Foo = Foo;
fn main() {
println!("0 drops follow this");
[FOO; 0];
println!("1 drops follow this");
[FOO; 1];
println!("2 drops follow this");
[FOO; 2];
}
While the stabilization of array-repeat expressions on constant values was accidental (#79270), people appear to be in agreement that this behavior is correct: #79270 (comment) . Specifically, it is considered correct that a constant array repeat expression [FOO; N]
will run FOO
's destructor N times.
Consider how this compares to the use of array-repeat expressions in non-constant contexts. For some non-constant expression [foo; N]
where foo impls Drop
:
-
When N is greater than 2, this will produce an insurmountable compile-time error (the compiler requires
Copy
, which is incompatible withDrop
). -
When N is 1, this will have identical results to the const-context array-repeat expression, and is not a problem.
-
When N is 0, this will run the destructor exactly once, which differs from the behavior of const-context array-repeat expressions, which will not run any destructor. (Technically this is contingent on Initializing a zero-length array leaks the initializer #74836 being fixed, but everybody agrees that the current leaking behavior is incorrect).
In light of this divergence of behavior between const and non-const array-repeat expressions, it's worth discussing whether #74857 should be revived, especially since the fix is as simple as not using [foo; 0]
and simply using []
instead.