diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 65bcb241e4a..f299aa0124d 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1213,6 +1213,9 @@ pub const fn allocator(b: &Self) -> &A { /// let static_ref: &'static mut usize = Box::leak(x); /// *static_ref += 1; /// assert_eq!(*static_ref, 42); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # drop(unsafe { Box::from_raw(static_ref) }); /// ``` /// /// Unsized data: @@ -1222,6 +1225,9 @@ pub const fn allocator(b: &Self) -> &A { /// let static_ref = Box::leak(x); /// static_ref[0] = 4; /// assert_eq!(*static_ref, [4, 2, 3]); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # drop(unsafe { Box::from_raw(static_ref) }); /// ``` #[stable(feature = "box_leak", since = "1.26.0")] #[inline] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index aa8dd9f79c3..9982c8ea6dc 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1277,6 +1277,8 @@ pub unsafe fn from_raw(ptr: *const T) -> Self { /// /// let five = Rc::from_raw(ptr); /// assert_eq!(2, Rc::strong_count(&five)); + /// # // Prevent leaks for Miri. + /// # Rc::decrement_strong_count(ptr); /// } /// ``` #[inline] @@ -1345,6 +1347,8 @@ pub fn allocator(this: &Self) -> &A { /// let x = Rc::new("hello".to_owned()); /// let x_ptr = Rc::into_raw(x); /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// # // Prevent leaks for Miri. + /// # drop(unsafe { Rc::from_raw(x_ptr) }); /// ``` #[must_use = "losing the pointer will leak memory"] #[stable(feature = "rc_raw", since = "1.17.0")] @@ -1572,6 +1576,8 @@ pub fn strong_count(this: &Self) -> usize { /// /// let five = Rc::from_raw_in(ptr, System); /// assert_eq!(2, Rc::strong_count(&five)); + /// # // Prevent leaks for Miri. + /// # Rc::decrement_strong_count_in(ptr, System); /// } /// ``` #[inline] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 36078da7c35..07ffd3e1519 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1984,6 +1984,9 @@ pub fn into_boxed_str(self) -> Box { /// let x = String::from("bucket"); /// let static_ref: &'static mut str = x.leak(); /// assert_eq!(static_ref, "bucket"); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # drop(unsafe { Box::from_raw(static_ref) }); /// ``` #[stable(feature = "string_leak", since = "1.72.0")] #[inline] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 57ac20ba323..a905a1e6b7e 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1414,6 +1414,8 @@ pub unsafe fn from_raw(ptr: *const T) -> Self { /// // the `Arc` between threads. /// let five = Arc::from_raw(ptr); /// assert_eq!(2, Arc::strong_count(&five)); + /// # // Prevent leaks for Miri. + /// # Arc::decrement_strong_count(ptr); /// } /// ``` #[inline] @@ -1484,6 +1486,8 @@ pub fn allocator(this: &Self) -> &A { /// let x = Arc::new("hello".to_owned()); /// let x_ptr = Arc::into_raw(x); /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// # // Prevent leaks for Miri. + /// # drop(unsafe { Arc::from_raw(x_ptr) }); /// ``` #[must_use = "losing the pointer will leak memory"] #[stable(feature = "rc_raw", since = "1.17.0")] @@ -1766,6 +1770,8 @@ pub fn strong_count(this: &Self) -> usize { /// // the `Arc` between threads. /// let five = Arc::from_raw_in(ptr, System); /// assert_eq!(2, Arc::strong_count(&five)); + /// # // Prevent leaks for Miri. + /// # Arc::decrement_strong_count_in(ptr, System); /// } /// ``` #[inline] diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 3bd89eaa6cb..10f62e4bb62 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -120,10 +120,15 @@ fn as_raw_mut_slice(&mut self) -> *mut [T] { /// This is roughly equivalent to the following, but more efficient /// /// ``` - /// # let mut into_iter = Vec::::with_capacity(10).into_iter(); + /// # let mut vec = Vec::::with_capacity(10); + /// # let ptr = vec.as_mut_ptr(); + /// # let mut into_iter = vec.into_iter(); /// let mut into_iter = std::mem::replace(&mut into_iter, Vec::new().into_iter()); /// (&mut into_iter).for_each(drop); /// std::mem::forget(into_iter); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # drop(unsafe { Vec::::from_raw_parts(ptr, 0, 10) }); /// ``` /// /// This method is used by in-place iteration, refer to the vec::in_place_collect diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6e9b017ad75..729d5dd4fe4 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1473,6 +1473,9 @@ pub fn allocator(&self) -> &A { /// // 2. `0 <= capacity` always holds whatever `capacity` is. /// unsafe { /// vec.set_len(0); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # vec.set_len(3); /// } /// ``` /// @@ -2391,6 +2394,9 @@ pub fn resize_with(&mut self, new_len: usize, f: F) /// let static_ref: &'static mut [usize] = x.leak(); /// static_ref[0] += 1; /// assert_eq!(static_ref, &[2, 2, 3]); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # drop(unsafe { Box::from_raw(static_ref) }); /// ``` #[stable(feature = "vec_leak", since = "1.47.0")] #[inline] diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index e0c3b9f3b51..997f088c6d6 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -62,6 +62,9 @@ impl ManuallyDrop { /// x.truncate(5); // You can still safely operate on the value /// assert_eq!(*x, "Hello"); /// // But `Drop` will not be run here + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # let _ = ManuallyDrop::into_inner(x); /// ``` #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"] #[stable(feature = "manually_drop", since = "1.20.0")] diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 24ebe33bb2c..dd40f57dc87 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -274,6 +274,8 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let v: MaybeUninit> = MaybeUninit::new(vec![42]); + /// # // Prevent leaks for Miri + /// # unsafe { let _ = MaybeUninit::assume_init(v); } /// ``` /// /// [`assume_init`]: MaybeUninit::assume_init @@ -446,6 +448,9 @@ pub const fn zeroed() -> MaybeUninit { /// let mut x = MaybeUninit::::uninit(); /// /// x.write("Hello".to_string()); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # unsafe { MaybeUninit::assume_init_drop(&mut x); } /// // This leaks the contained string: /// x.write("hello".to_string()); /// // x is initialized now: @@ -506,6 +511,8 @@ pub const fn write(&mut self, val: T) -> &mut T { /// // Create a reference into the `MaybeUninit`. This is okay because we initialized it. /// let x_vec = unsafe { &*x.as_ptr() }; /// assert_eq!(x_vec.len(), 3); + /// # // Prevent leaks for Miri + /// # unsafe { MaybeUninit::assume_init_drop(&mut x); } /// ``` /// /// *Incorrect* usage of this method: @@ -545,6 +552,8 @@ pub const fn as_ptr(&self) -> *const T { /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; /// x_vec.push(3); /// assert_eq!(x_vec.len(), 4); + /// # // Prevent leaks for Miri + /// # unsafe { MaybeUninit::assume_init_drop(&mut x); } /// ``` /// /// *Incorrect* usage of this method: @@ -746,6 +755,8 @@ pub unsafe fn assume_init_drop(&mut self) { /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); + /// # let mut x_mu = x; + /// # let mut x = &mut x_mu; /// // Initialize `x`: /// x.write(vec![1, 2, 3]); /// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to @@ -755,6 +766,8 @@ pub unsafe fn assume_init_drop(&mut self) { /// x.assume_init_ref() /// }; /// assert_eq!(x, &vec![1, 2, 3]); + /// # // Prevent leaks for Miri + /// # unsafe { MaybeUninit::assume_init_drop(&mut x_mu); } /// ``` /// /// ### *Incorrect* usages of this method: @@ -1088,6 +1101,8 @@ pub fn copy_from_slice<'a>(this: &'a mut [MaybeUninit], src: &[T]) -> &'a mut /// let init = MaybeUninit::clone_from_slice(&mut dst, &src); /// /// assert_eq!(init, src); + /// # // Prevent leaks for Miri + /// # unsafe { std::ptr::drop_in_place(init); } /// ``` /// /// ``` diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 75a99e14fda..1238061d68d 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1663,6 +1663,8 @@ pub const fn as_mut_ptr(self) -> *mut T { /// // Note that calling `memory.as_mut()` is not allowed here as the content may be uninitialized. /// # #[allow(unused_variables)] /// let slice: &mut [MaybeUninit] = unsafe { memory.as_uninit_slice_mut() }; + /// # // Prevent leaks for Miri. + /// # unsafe { Global.deallocate(memory.cast(), Layout::new::<[u8; 32]>()); } /// # Ok::<_, std::alloc::AllocError>(()) /// ``` #[inline] diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs index f9f83fb4f63..08d46f356d9 100644 --- a/library/std/src/sync/condvar.rs +++ b/library/std/src/sync/condvar.rs @@ -35,6 +35,7 @@ impl WaitTimeoutResult { /// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair2 = Arc::clone(&pair); /// + /// # let handle = /// thread::spawn(move || { /// let (lock, cvar) = &*pair2; /// @@ -58,6 +59,8 @@ impl WaitTimeoutResult { /// break /// } /// } + /// # // Prevent leaks for Miri. + /// # let _ = handle.join(); /// ``` #[must_use] #[stable(feature = "wait_timeout", since = "1.5.0")] diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index cab37e0da47..3d977bf3058 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -58,9 +58,8 @@ check-aux: library/core \ library/alloc \ --no-doc - # Some doctests have intentional memory leaks. - # Some use file system operations to demonstrate dealing with `Result`. - $(Q)MIRIFLAGS="-Zmiri-ignore-leaks -Zmiri-disable-isolation" \ + # Some doctests use file system operations to demonstrate dealing with `Result`. + $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ $(BOOTSTRAP) miri --stage 2 \ library/core \ library/alloc \ @@ -70,7 +69,7 @@ check-aux: $(BOOTSTRAP) miri --stage 2 library/std \ --no-doc -- \ --skip fs:: --skip net:: --skip process:: --skip sys::pal:: - $(Q)MIRIFLAGS="-Zmiri-ignore-leaks -Zmiri-disable-isolation" \ + $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ $(BOOTSTRAP) miri --stage 2 library/std \ --doc -- \ --skip fs:: --skip net:: --skip process:: --skip sys::pal::