Repository navigation
Closed
Labels
A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlA-destructorsArea: Destructors (`Drop`, …)Area: Destructors (`Drop`, …)A-patternsRelating to patterns and pattern matchingRelating to patterns and pattern matchingC-bugCategory: This is a bug.Category: This is a bug.P-criticalCritical priorityCritical priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Description
I found a bug where Rust leaks values (never calls drop). This is the root cause of a memory leak we saw in a Fuchsia test, caught by LeakSanitizer: https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=87961.
This is as far as I could minimize it:
#![allow(unused)]
struct S(u32);
impl Drop for S {
fn drop(&mut self) {
println!("dropping {}", self.0);
}
}
enum E {
A,
B((S, S)),
}
fn main() {
let mut foo = Some(E::A);
match foo {
Some(E::A) => (),
_ => return,
}
foo.insert(E::B((S(1), S(2))));
match foo {
Some(E::B((x, _))) => {}
_ => {}
}
}Expected output:
dropping 2
dropping 1
Actual output:
dropping 1
It leaked S(2). If you change (x, _) to (_, x) in the second match statement, it leaks S(1) instead. If you bind neither (_, _) or both (x, y), then both get dropped as expected.
If you use Box<u8> instead of S, you can detect a memory leak using LeakSanitizer or Valgrind.
Meta
I reproduced this on stable:
rustc 1.56.1 (59eed8a2a 2021-11-01)
binary: rustc
commit-hash: 59eed8a2aac0230a8b53e89d4e99d55912ba6b35
commit-date: 2021-11-01
host: x86_64-unknown-linux-gnu
release: 1.56.1
LLVM version: 13.0.0
And on nightly:
rustc 1.58.0-nightly (8b09ba6a5 2021-11-09)
binary: rustc
commit-hash: 8b09ba6a5d5c644fe0f1c27c7f9c80b334241707
commit-date: 2021-11-09
host: x86_64-unknown-linux-gnu
release: 1.58.0-nightly
LLVM version: 13.0.0
Reacted by Tyler Mandry, Marcel Hellwig, Hans Kratz and Dylan MacKenzie
Metadata
Metadata
Assignees
Labels
A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlA-destructorsArea: Destructors (`Drop`, …)Area: Destructors (`Drop`, …)A-patternsRelating to patterns and pattern matchingRelating to patterns and pattern matchingC-bugCategory: This is a bug.Category: This is a bug.P-criticalCritical priorityCritical priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Activity
jyn514 commentedon Nov 10, 2021
Note that the miscompilation goes away if you change
foo.insert((E::B)tofoo = Some(E::B). So I suspect theunreachable_uncheckedin insert is what's causing this somehow.rust/library/core/src/option.rs
Line 1211 in e5cfe84
jyn514 commentedon Nov 10, 2021
Also, the miscompilation is in MIR, not LLVM, because Miri also fails to run the destructor.
jyn514 commentedon Nov 10, 2021
Very slightly smaller (I removed the fields in
S):jyn514 commentedon Nov 10, 2021
Oh strangely this is not related to the
unwrap_unchecked, it still reproduces with a normalunwrap. https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=6e6a87916e94f4012b2d93615a7ce1d1jyn514 commentedon Nov 10, 2021
Here's a version without
std::option::Option(just an in-crate option): https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=025985867f32378dad0785597377a680nbdd0121 commentedon Nov 10, 2021
A quick manual bisection on godbolt shows that this regresses in Rust 1.43 (is correct in Rust 1.42).
@rustbot label: regression-from-stable-to-stable
nbdd0121 commentedon Nov 10, 2021
Bisection reveals that this issue is introduced in #68528.
I think the issue is that precise_enum_drop_elaboration didn't re-mark all variants as possibly active after the mutable reference to the enum is used. The miscompilation goes away with
-Z precise_enum_drop_elaboration=n. I filed #90756 to disable precise_enum_drop_elaboration by default, and we can turn this back on once the issue is fixed.cc @ecstatic-morse
@rustbot label: +A-mir
13 remaining items
Add raw pointer variant of rust-lang#90752 with incorrect behavior
apiraino commentedon Nov 18, 2021
Assigning priority as discussed in the Zulip thread of the Prioritization Working Group.
@rustbot label -I-prioritize +P-critical
pnkfelix commentedon Dec 2, 2021
FYI This is addressed by PR #90788, which will be part of the Rust 1.58 release (stable in six weeks).
apiraino commentedon Jan 20, 2022
Checking progress, @mk12 did you have a chance to test against the new stable 1.58 if it solves the issue? thanks
mk12 commentedon Jan 22, 2022
@apiraino The example I gave in my first comment now behaves as expected on the Rust playground with 1.58.1 stable. I'm fairly sure this solves the original Fuchsia bug, but it's difficult to reproduce that because a workaround was used at the time and that code has changed a lot since.
apiraino commentedon Jan 27, 2022
I'm going to close this issue as we think it's solved. In case it can be reopened or follow-up issues can be created