diff options
| author | bors <bors@rust-lang.org> | 2021-11-23 17:44:33 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-11-23 17:44:33 +0000 |
| commit | 7b3cd075bbe309031b418650a9c32baf0b4a3276 (patch) | |
| tree | 3497a521d0204eb2a83f6659c429c50576ebd693 /src/test/ui/drop | |
| parent | 311fa1f14dd8ffbbe83b229a94b17f7f1ecaf33b (diff) | |
| parent | 22d937ddfc64bdf1f8724a27a782f2da2ae72be0 (diff) | |
| download | rust-7b3cd075bbe309031b418650a9c32baf0b4a3276.tar.gz rust-7b3cd075bbe309031b418650a9c32baf0b4a3276.zip | |
Auto merge of #90788 - ecstatic-morse:issue-90752, r=wesleywiser
Mark places as initialized when mutably borrowed Fixes the example in #90752, but does not handle some corner cases involving raw pointers and unsafe. See [this comment](https://github.com/rust-lang/rust/issues/90752#issuecomment-965822895) for more information, or the second test. Although I talked about both `MaybeUninitializedPlaces` and `MaybeInitializedPlaces` in #90752, this PR only changes the latter. That's because "maybe uninitialized" is the conservative choice, and marking them as definitely initialized (`!maybe_uninitialized`) when a mutable borrow is created could lead to problems if `addr_of_mut` to an uninitialized local is allowed. Additionally, places cannot become uninitialized via a mutable reference, so if a place is definitely initialized, taking a mutable reference to it should not change that. I think it's correct to ignore interior mutability as nbdd0121 suggests below. Their analysis doesn't work inside of `core::cell`, which *does* have access to `UnsafeCell`'s field, but that won't be an issue unless we explicitly instantiate one with an `enum` within that module. r? `@wesleywiser`
Diffstat (limited to 'src/test/ui/drop')
| -rw-r--r-- | src/test/ui/drop/issue-90752-raw-ptr-shenanigans.rs | 41 | ||||
| -rw-r--r-- | src/test/ui/drop/issue-90752.rs | 32 |
2 files changed, 73 insertions, 0 deletions
diff --git a/src/test/ui/drop/issue-90752-raw-ptr-shenanigans.rs b/src/test/ui/drop/issue-90752-raw-ptr-shenanigans.rs new file mode 100644 index 00000000000..4e67b35949e --- /dev/null +++ b/src/test/ui/drop/issue-90752-raw-ptr-shenanigans.rs @@ -0,0 +1,41 @@ +// run-pass + +use std::cell::RefCell; + +struct S<'a>(i32, &'a RefCell<Vec<i32>>); + +impl<'a> Drop for S<'a> { + fn drop(&mut self) { + self.1.borrow_mut().push(self.0); + } +} + +fn test(drops: &RefCell<Vec<i32>>) { + let mut foo = None; + let pfoo: *mut _ = &mut foo; + + match foo { + None => (), + _ => return, + } + + // Both S(0) and S(1) should be dropped, but aren't. + unsafe { *pfoo = Some((S(0, drops), S(1, drops))); } + + match foo { + Some((_x, _)) => {} + _ => {} + } +} + +fn main() { + let drops = RefCell::new(Vec::new()); + test(&drops); + + // Ideally, we want this... + //assert_eq!(*drops.borrow(), &[0, 1]); + + // But the delayed access through the raw pointer confuses drop elaboration, + // causing S(1) to be leaked. + assert_eq!(*drops.borrow(), &[0]); +} diff --git a/src/test/ui/drop/issue-90752.rs b/src/test/ui/drop/issue-90752.rs new file mode 100644 index 00000000000..4395e45e773 --- /dev/null +++ b/src/test/ui/drop/issue-90752.rs @@ -0,0 +1,32 @@ +// run-pass + +use std::cell::RefCell; + +struct S<'a>(i32, &'a RefCell<Vec<i32>>); + +impl<'a> Drop for S<'a> { + fn drop(&mut self) { + self.1.borrow_mut().push(self.0); + } +} + +fn test(drops: &RefCell<Vec<i32>>) { + let mut foo = None; + match foo { + None => (), + _ => return, + } + + *(&mut foo) = Some((S(0, drops), S(1, drops))); // Both S(0) and S(1) should be dropped + + match foo { + Some((_x, _)) => {} + _ => {} + } +} + +fn main() { + let drops = RefCell::new(Vec::new()); + test(&drops); + assert_eq!(*drops.borrow(), &[0, 1]); +} |
