Skip to content

Mutable reference protected by a mutex in static context is considered UB #120450

Closed
Listed in
@sysheap

Description

@sysheap

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

added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Jan 28, 2024
saethlin

saethlin commented on Jan 28, 2024

@saethlin
Member

In my head the compiler need to look at the Sync trait and if it is implement by a type, this is not UB.

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:

throw_validation_failure!(self.path, MutableRefInConst);

added
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
C-feature-requestCategory: A feature request, i.e: not implemented / a PR.
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)
and removed
C-bugCategory: This is a bug.
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Jan 28, 2024
sysheap

sysheap commented on Feb 4, 2024

@sysheap
Author

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

saethlin commented on Feb 4, 2024

@saethlin
Member

Trait bounds are not related. Looking through the tracking issue for const_mut_refs, this seems relevant: #57349 (comment)

RalfJung

RalfJung commented on Feb 15, 2024

@RalfJung
Member

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 stabilizing const_mut_refs.
Cc @oli-obk

RalfJung

RalfJung commented on Feb 15, 2024

@RalfJung
Member

Urgh, this is a nasty interaction. This gets rejected the way it should:

static MUTABLE_REFERENCE_HOLDER: Mutex<&mut [u8]> = Mutex::new(&mut [1]);
// ERROR: error[E0716]: temporary value dropped while borrowed

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

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)C-feature-requestCategory: A feature request, i.e: not implemented / a PR.F-const_mut_refs`#![feature(const_mut_refs)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Participants

    @RalfJung@oli-obk@sysheap@saethlin@rustbot

    Issue actions

      Mutable reference protected by a mutex in static context is considered UB · Issue #120450 · rust-lang/rust