miri:error printing the return value of align_to_mut
rodrimati1992 opened this issue · 3 comments
Attempting to run this code:
fn main() {
dbg!(unsafe { [1u8,2,3,4,5].align_to_mut::<[u8;2]>() });
}
in miri 2020-01-15 in the playground,results in this error:
[src/main.rs:2] unsafe { [1u8, 2, 3, 4, 5].align_to_mut::<[u8; 2]>() } = (
[],
error: Miri evaluation error: trying to reborrow for SharedReadOnly, but parent tag <1287> does not have an appropriate item in the borrow stack
--> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1963:71
|
1963 | fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) }
| ^^^^^^^ trying to reborrow for SharedReadOnly, but parent tag <1287> does not have an appropriate item in the borrow stack
|
= note: inside call to `<&mut [[u8; 2]] as std::fmt::Debug>::fmt` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1959:81
= note: inside call to `<&&mut [[u8; 2]] as std::fmt::Debug>::fmt` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/builders.rs:342:17
= note: inside call to closure at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/result.rs:721:22
= note: inside call to `std::result::Result::<(), std::fmt::Error>::and_then::<(), [closure@DefId(2:5728 ~ core[279e]::fmt[0]::builders[0]::{{impl}}[4]::field[0]::{{closure}}[0]) 0:&mut &mut std::fmt::DebugTuple, 1:&&dyn std::fmt::Debug]>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/builders.rs:334:23
= note: inside call to `std::fmt::DebugTuple::field` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:2128:21
= note: inside call to `<&(&mut [u8], &mut [[u8; 2]], &mut [u8]) as std::fmt::Debug>::fmt` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1097:5
= note: inside call to `core::fmt::run` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1061:17
= note: inside call to `std::fmt::write` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/io/mod.rs:1426:15
= note: inside call to `<std::io::StderrLock as std::io::Write>::write_fmt` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/io/stdio.rs:706:9
= note: inside call to `<std::io::Stderr as std::io::Write>::write_fmt` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/io/stdio.rs:800:13
= note: inside call to closure at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/thread/local.rs:262:16
= note: inside call to `std::thread::LocalKey::<std::cell::RefCell<std::option::Option<std::boxed::Box<dyn std::io::Write + std::marker::Send>>>>::try_with::<[closure@DefId(1:2778 ~ std[8be3]::io[0]::stdio[0]::print_to[0]::{{closure}}[0]) 0:&std::fmt::Arguments, 1:&fn() -> std::io::Stderr], std::result::Result<(), std::io::Error>>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/io/stdio.rs:793:18
= note: inside call to `std::io::stdio::print_to::<std::io::Stderr>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/io/stdio.rs:828:5
note: inside call to `std::io::_eprint` at <::std::macros::eprintln macros>:2:4
--> src/main.rs:2:5
|
2 | dbg!(unsafe { [1u8,2,3,4,5].align_to_mut::<[u8;2]>() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: inside call to `main` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:67:34
= note: inside call to closure at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:52:73
= note: inside call to closure at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/sys_common/backtrace.rs:129:5
= note: inside call to `std::sys_common::backtrace::__rust_begin_short_backtrace::<[closure@DefId(1:6019 ~ std[8be3]::rt[0]::lang_start_internal[0]::{{closure}}[0]::{{closure}}[0]) 0:&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:52:13
= note: inside call to closure at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/panicking.rs:305:40
= note: inside call to `std::panicking::r#try::do_call::<[closure@DefId(1:6018 ~ std[8be3]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/panicking.rs:281:13
= note: inside call to `std::panicking::r#try::<i32, [closure@DefId(1:6018 ~ std[8be3]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe]>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/panic.rs:394:14
= note: inside call to `std::panic::catch_unwind::<[closure@DefId(1:6018 ~ std[8be3]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:51:25
= note: inside call to `std::rt::lang_start_internal` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:67:5
= note: inside call to `std::rt::lang_start::<()>`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error
error: could not compile `playground`.
Code of that function:
pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) {
// Note that most of this function will be constant-evaluated,
if mem::size_of::<U>() == 0 || mem::size_of::<T>() == 0 {
// handle ZSTs specially, which is – don't handle them at all.
return (self, &mut [], &mut []);
}
// First, find at what point do we split between the first and 2nd slice. Easy with
// ptr.align_offset.
let ptr = self.as_ptr();
let offset = crate::ptr::align_offset(ptr, mem::align_of::<U>());
if offset > self.len() {
(self, &mut [], &mut [])
} else {
let (left, rest) = self.split_at_mut(offset);
// now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay
let (us_len, ts_len) = rest.align_to_offsets::<U>();
let mut_ptr = rest.as_mut_ptr();
(
left,
from_raw_parts_mut(mut_ptr as *mut U, us_len),
from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len),
)
}
}
Somewhat simplified:
fn main() {
unsafe {
([1u8,2,3,4,5].align_to_mut::<[u8;2]>().1)[0]
};
}
Replacing [u8;2]
with u16
makes miri shut up, even though the two types should be mostly equivalent.
If it is really a problem with how the align_to_mut
function is implemented, the pointer cast in from_raw_parts_mut(mut_ptr as *mut U, us_len)
is going to be it – though I believe I’ve done due diligence in making sure this code is valid for as long as transmuting T
to U
is valid.
cc @RalfJung
This is where the tag gets removed from the borrow stack:
$ ./miri run-debug align.rs -Zmiri-track-pointer-tag=1287
note: popped tracked tag for item [Unique for <1287>]
--> /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libcore/slice/mod.rs:2515:48
|
2515 | from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len),
| ^^^^^^^^^^ popped tracked tag for item [Unique for <1287>]
|
note: inside call to `core::slice::<impl [u8]>::align_to_mut::<[u8; 2]>` at align.rs:3:10
--> align.rs:3:10
|
3 | ([1u8,2,3,4,5].align_to_mut::<[u8;2]>().1)[0]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The problem is that rest.len()
creates a new &[u8]
that overlaps with the already created &mut [u8]
.
Replacing [u8;2] with u16 makes miri shut up, even though the two types should be mostly equivalent.
It also makes the middle slice empty, so there is no overlap.