Skip to content

Commit 255fdcc

Browse files
authored
Rollup merge of #121782 - RalfJung:mutable-ref-in-static, r=oli-obk
allow statics pointing to mutable statics Fixes #120450 for good. We can even simplify our checks: no need to specifically go looking for mutable references in const, we can just reject any reference that points to something mutable. r? `@oli-obk`
2 parents 2fdcdd9 + a9596fb commit 255fdcc

File tree

12 files changed

+64
-307
lines changed

12 files changed

+64
-307
lines changed

Diff for: compiler/rustc_const_eval/messages.ftl

-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,6 @@ const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, bu
453453
const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
454454
const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
455455
const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
456-
const_eval_validation_mutable_ref_in_const_or_static = {$front_matter}: encountered mutable reference in a `const` or `static`
457456
const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory
458457
const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
459458
const_eval_validation_null_box = {$front_matter}: encountered a null box

Diff for: compiler/rustc_const_eval/src/errors.rs

-2
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,6 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
613613
PartialPointer => const_eval_validation_partial_pointer,
614614
ConstRefToMutable => const_eval_validation_const_ref_to_mutable,
615615
ConstRefToExtern => const_eval_validation_const_ref_to_extern,
616-
MutableRefInConstOrStatic => const_eval_validation_mutable_ref_in_const_or_static,
617616
MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable,
618617
NullFnPtr => const_eval_validation_null_fn_ptr,
619618
NeverVal => const_eval_validation_never_val,
@@ -767,7 +766,6 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
767766
}
768767
NullPtr { .. }
769768
| PtrToStatic { .. }
770-
| MutableRefInConstOrStatic
771769
| ConstRefToMutable
772770
| ConstRefToExtern
773771
| MutableRefToImmutable

Diff for: compiler/rustc_const_eval/src/interpret/validity.rs

+8-17
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,6 @@ impl CtfeValidationMode {
148148
}
149149
}
150150
}
151-
152-
fn may_contain_mutable_ref(self) -> bool {
153-
match self {
154-
CtfeValidationMode::Static { mutbl } => mutbl == Mutability::Mut,
155-
CtfeValidationMode::Promoted { .. } => false,
156-
CtfeValidationMode::Const { .. } => false,
157-
}
158-
}
159151
}
160152

161153
/// State for tracking recursive validation of references
@@ -511,20 +503,19 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
511503
// If this allocation has size zero, there is no actual mutability here.
512504
let (size, _align, _alloc_kind) = self.ecx.get_alloc_info(alloc_id);
513505
if size != Size::ZERO {
506+
// Mutable pointer to immutable memory is no good.
514507
if ptr_expected_mutbl == Mutability::Mut
515508
&& alloc_actual_mutbl == Mutability::Not
516509
{
517510
throw_validation_failure!(self.path, MutableRefToImmutable);
518511
}
519-
if ptr_expected_mutbl == Mutability::Mut
520-
&& self.ctfe_mode.is_some_and(|c| !c.may_contain_mutable_ref())
521-
{
522-
throw_validation_failure!(self.path, MutableRefInConstOrStatic);
523-
}
524-
if alloc_actual_mutbl == Mutability::Mut
525-
&& matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
526-
{
527-
throw_validation_failure!(self.path, ConstRefToMutable);
512+
// In a const, everything must be completely immutable.
513+
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) {
514+
if ptr_expected_mutbl == Mutability::Mut
515+
|| alloc_actual_mutbl == Mutability::Mut
516+
{
517+
throw_validation_failure!(self.path, ConstRefToMutable);
518+
}
528519
}
529520
}
530521
// Potentially skip recursive check.

Diff for: compiler/rustc_middle/src/mir/interpret/error.rs

-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,6 @@ pub enum ValidationErrorKind<'tcx> {
420420
PartialPointer,
421421
PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
422422
PtrToStatic { ptr_kind: PointerKind },
423-
MutableRefInConstOrStatic,
424423
ConstRefToMutable,
425424
ConstRefToExtern,
426425
MutableRefToImmutable,

Diff for: tests/ui/consts/const-mut-refs/const_mut_refs.rs

+5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ const fn bazz(foo: &mut Foo) -> usize {
3333
// Empty slices get promoted so this passes the static checks.
3434
// Make sure it also passes the dynamic checks.
3535
static MUTABLE_REFERENCE_HOLDER: Mutex<&mut [u8]> = Mutex::new(&mut []);
36+
// This variant with a non-empty slice also seems entirely reasonable.
37+
static MUTABLE_REFERENCE_HOLDER2: Mutex<&mut [u8]> = unsafe {
38+
static mut FOO: [u8; 1] = [42]; // a private static that we are sure nobody else will reference
39+
Mutex::new(&mut *std::ptr::addr_of_mut!(FOO))
40+
};
3641

3742
fn main() {
3843
let _: [(); foo().bar()] = [(); 1];

Diff for: tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ const fn helper() -> Option<&'static mut i32> { unsafe {
1818
Some(&mut *std::ptr::addr_of_mut!(BUFFER))
1919
} }
2020
const MUT: Option<&mut i32> = helper(); //~ ERROR it is undefined behavior to use this value
21-
//~^ encountered mutable reference
22-
static MUT_STATIC: Option<&mut i32> = helper(); //~ ERROR it is undefined behavior to use this value
23-
//~^ encountered mutable reference
21+
//~^ encountered reference to mutable
2422

2523
const fn helper_int2ptr() -> Option<&'static mut i32> { unsafe {
2624
// Undefined behaviour (integer as pointer), who doesn't love tests like this.
@@ -38,11 +36,9 @@ const fn helper_dangling() -> Option<&'static mut i32> { unsafe {
3836
const DANGLING: Option<&mut i32> = helper_dangling(); //~ ERROR encountered dangling pointer
3937
static DANGLING_STATIC: Option<&mut i32> = helper_dangling(); //~ ERROR encountered dangling pointer
4038

41-
// Variant of the real-world case in <https://github.com/rust-lang/rust/issues/120450>.
42-
// Maybe we should allow this in the future (then the rest should move to `const_mut_refs.rs`),
43-
// but for now we reject it.
39+
// These are fine! Just statics pointing to mutable statics, nothing fundamentally wrong with this.
40+
static MUT_STATIC: Option<&mut i32> = helper();
4441
static mut MUT_ARRAY: &mut [u8] = &mut [42];
45-
static MUTEX: Mutex<&mut [u8]> = Mutex::new(unsafe { &mut *MUT_ARRAY }); //~ ERROR it is undefined behavior to use this value
46-
//~^ encountered mutable reference
42+
static MUTEX: Mutex<&mut [u8]> = Mutex::new(unsafe { &mut *MUT_ARRAY });
4743

4844
fn main() {}

Diff for: tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr

+6-28
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,15 @@ error[E0080]: it is undefined behavior to use this value
22
--> $DIR/mut_ref_in_final_dynamic_check.rs:20:1
33
|
44
LL | const MUT: Option<&mut i32> = helper();
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0: encountered mutable reference in a `const` or `static`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0: encountered reference to mutable memory in `const`
66
|
77
= 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.
88
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
99
HEX_DUMP
1010
}
1111

1212
error[E0080]: it is undefined behavior to use this value
13-
--> $DIR/mut_ref_in_final_dynamic_check.rs:22:1
14-
|
15-
LL | static MUT_STATIC: Option<&mut i32> = helper();
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0: encountered mutable reference in a `const` or `static`
17-
|
18-
= 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.
19-
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
20-
HEX_DUMP
21-
}
22-
23-
error[E0080]: it is undefined behavior to use this value
24-
--> $DIR/mut_ref_in_final_dynamic_check.rs:29:1
13+
--> $DIR/mut_ref_in_final_dynamic_check.rs:27:1
2514
|
2615
LL | const INT2PTR: Option<&mut i32> = helper_int2ptr();
2716
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0: encountered a dangling reference (0x2a[noalloc] has no provenance)
@@ -32,7 +21,7 @@ LL | const INT2PTR: Option<&mut i32> = helper_int2ptr();
3221
}
3322

3423
error[E0080]: it is undefined behavior to use this value
35-
--> $DIR/mut_ref_in_final_dynamic_check.rs:31:1
24+
--> $DIR/mut_ref_in_final_dynamic_check.rs:29:1
3625
|
3726
LL | static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr();
3827
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0: encountered a dangling reference (0x2a[noalloc] has no provenance)
@@ -43,28 +32,17 @@ LL | static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr();
4332
}
4433

4534
error: encountered dangling pointer in final value of constant
46-
--> $DIR/mut_ref_in_final_dynamic_check.rs:38:1
35+
--> $DIR/mut_ref_in_final_dynamic_check.rs:36:1
4736
|
4837
LL | const DANGLING: Option<&mut i32> = helper_dangling();
4938
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5039

5140
error: encountered dangling pointer in final value of static
52-
--> $DIR/mut_ref_in_final_dynamic_check.rs:39:1
41+
--> $DIR/mut_ref_in_final_dynamic_check.rs:37:1
5342
|
5443
LL | static DANGLING_STATIC: Option<&mut i32> = helper_dangling();
5544
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5645

57-
error[E0080]: it is undefined behavior to use this value
58-
--> $DIR/mut_ref_in_final_dynamic_check.rs:45:1
59-
|
60-
LL | static MUTEX: Mutex<&mut [u8]> = Mutex::new(unsafe { &mut *MUT_ARRAY });
61-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .data.value: encountered mutable reference in a `const` or `static`
62-
|
63-
= 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.
64-
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
65-
HEX_DUMP
66-
}
67-
68-
error: aborting due to 7 previous errors
46+
error: aborting due to 5 previous errors
6947

7048
For more information about this error, try `rustc --explain E0080`.

Diff for: tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr

-180
This file was deleted.

Diff for: tests/ui/consts/miri_unleashed/mutable_references_err.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
//@ stderr-per-bitwidth
21
//@ compile-flags: -Zunleash-the-miri-inside-of-you
2+
//@ normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
3+
//@ normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
34
#![allow(invalid_reference_casting, static_mut_refs)]
45

56
use std::cell::UnsafeCell;

0 commit comments

Comments
 (0)