Description
I tried this code:
#![feature(const_mut_refs)]
use std::sync::Mutex;
static MUTABLE_REFERENCE_HOLDER: Mutex<&mut [u8]> = Mutex::new(&mut []);
fn main() {}
I expected to see this happen: This code should compile because the mutable reference is protected by a Mutex and therefore, it is safe to access.
Instead, this happened: I receive the following compiler error:
error[E0080]: it is undefined behavior to use this value
--> src/main.rs:5:1
|
5 | static MUTABLE_REFERENCE_HOLDER: Mutex<&mut [u8]> = Mutex::new(&mut []);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .data.value: encountered mutable reference in a `const` or `static`
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 24, align: 8) {
0x00 │ 00 00 00 00 00 __ __ __ ╾───────alloc3────────╼ │ .....░░░╾──────╼
0x10 │ 00 00 00 00 00 00 00 00 │ ........
}
I am not entirely sure if I'm missing something here. Is this UB or not?
Since a mutable reference to a slice of u8 is Send the mutex is Send + Sync. Therefore, I assume this should be allowed?
If this is in fact a mistake in the compiler, I'd be glad to try to provide a pull request with a fix. In my head the compiler need to look at the Sync trait and if it is implement by a type, this is not UB.
Meta
rustc --version --verbose
:
rustc 1.77.0-nightly (6b4f1c5e7 2024-01-27)
binary: rustc
commit-hash: 6b4f1c5e782c72a047a23e922decd33e7d462345
commit-date: 2024-01-27
host: x86_64-unknown-linux-gnu
release: 1.77.0-nightly
LLVM version: 17.0.6
Activity
saethlin commentedon Jan 28, 2024
I think you're assuming the problem is in type-checking, but if that were the case this would be an entirely different error message. This error comes out of
const
validation:rust/compiler/rustc_const_eval/src/interpret/validity.rs
Line 606 in 6351247
sysheap commentedon Feb 4, 2024
I'm new to the rust compiler, so please bear with me.
Is it even possible to fix the behavior I describend in the const validation? Do I have access to the information of a certain type implements Sync or not?
I tried to figure it out myself but didn't come that far...
Thanks!
saethlin commentedon Feb 4, 2024
Trait bounds are not related. Looking through the tracking issue for
const_mut_refs
, this seems relevant: #57349 (comment)page allocator: mutable references are disallowed in statics
RalfJung commentedon Feb 15, 2024
Oh interesting, is this a regression introduced by #119044?
Though we had
MutableRefInConst
already before that so probably, no. Still, we should figure out what to do with this before stabilizingconst_mut_refs
.Cc @oli-obk
&mut T
in const contexts (const_mut_refs) #57349RalfJung commentedon Feb 15, 2024
Urgh, this is a nasty interaction. This gets rejected the way it should:
But with an empty slice, it gets promoted, and so there's no issue with pointing to a temporary -- and so we reach const validation, where it gets rejected as expected.
We may have to adjust validity to make it so that "mutable reference to 0 bytes" is allowed. But I'm concerned that people might then unsafely turn that into a reference that covers more than 0 bytes and now we need subobject provenance to explain why their code is UB and I don't want to have subobject provenance.
What we could allow is a mutable reference that doesn't point to actual memory. I don't know what exactly the internal representation of the empty slice here will be, but that should be sufficient for this specific case.
23 remaining items