Change:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --The issue reproduces only if code resides in a separate crate and only if compiled in release configuration. I tried this code: 's crate : 's crate : I expected to see this happen: printed 20 times. Instead, this happened: printed 20 times in debug build, but not in release. Instead, slice length appears to be corrupted, so prints memory dump outside of allocated slice and eventually segfaults. However, if implementation for is removed, then slice is truncated to a single byte, which is still incorrect, but doesn't crash the process. If call is replaced with directly then everything works as intended even on release builds. If code placed in the same crate as then everything works as intended as well. Removing from fixed the issue as well. This reproduces on Linux and MacOS (haven't tried Windows). <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details
This passes under Miri, and it looks like the invariants for are being upheld.
:
I can reproduce this at least as far back as (although it's an infinite loop there, not a segfault). So I'd guess this isn't a regression and just never worked.
The slice length returned from FatPtr::deref is considered dead and eliminated by Dead Argument Elimination, that doesn't seem right since there are two calls to FatPtr::deref, one that uses returned ptr and the other one that uses returned length. <details<summaryMinimized LLVM IR</summary<p</p</details
Assigning as .
Nominating this for a discussion in T-compiler. While not a "regression" this issue seems just as bad if not worse than some other soundness holes that we’ve had at P-critical. And it seems like it could be fairly easy to trigger in typical code (and also that there could be an entirely safe reproducer for this issue).
This is caused by a bug in : After inspecting all of the users of a function's return values, is called for each return value: either calls (which propagates liveness dependencies using the global map), or updates the map with the dependencies that were computed earlier: However, the dependencies computed for higher-numbered return values can affect the calls for lower-numbered dependencies. That is, we may call for a before we have fully populated for that . One solution is to iterate over the return values in two passes - we update the map in the first pass, and call in the second pass.
LLVM bug report
This was and we decided to bump the priority to .
I'm working on a patch for LLVM
can we assign this issue to you then?
My LLVM patch is posted at The commit can be cherry-picked from
This
A different LLVM patch (which still fixes this issue) has been accepted:
do you know in which LLVM version is this going to be included?
it will be included in LLVM 12 which is expected around March/April.
The accepted patch is pretty small and self-contained, so I think we could cherry-pick it if we wanted to

Discussion:
<del> Subproject commit 655a1467c98741e332b87661a9046877077ef4dc </del> <ins> Subproject commit ee1617457899ef2eb55dcf7ee2758b4340b6533f </ins>

<ins> // compile-flags: -C opt-level=3 pub struct FatPtr { ptr: *mut u8, len: usize, } impl FatPtr { pub fn new(len: usize) -> FatPtr { let ptr = Box::into_raw(vec![42u8; len].into_boxed_slice()) as *mut u8; FatPtr { ptr, len } } } impl std::ops::Deref for FatPtr { type Target = [u8]; #[inline] fn deref(&self) -> &[u8] { unsafe { std::slice::from_raw_parts(self.ptr, self.len) } } } impl std::ops::Drop for FatPtr { fn drop(&mut self) { println!("Drop"); } } </ins>

<ins> // no-system-llvm // compile-flags: -C opt-level=3 // aux-build: issue-76387.rs // run-pass // Regression test for issue #76387 // Tests that LLVM doesn't miscompile this extern crate issue_76387; use issue_76387::FatPtr; fn print(data: &[u8]) { println!("{:#?}", data); } fn main() { let ptr = FatPtr::new(20); let data = unsafe { std::slice::from_raw_parts(ptr.as_ptr(), ptr.len()) }; print(data); } </ins>