Skip to content

Commit 1e43cc2

Browse files
committed
clarify and unify 'transient mutable borrow' errors
1 parent 5c945c9 commit 1e43cc2

31 files changed

+80
-107
lines changed

compiler/rustc_const_eval/messages.ftl

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,13 @@ const_eval_incompatible_return_types =
124124
const_eval_incompatible_types =
125125
calling a function with argument of type {$callee_ty} passing data of type {$caller_ty}
126126
127-
const_eval_interior_mutable_ref_escaping =
128-
{const_eval_const_context}s cannot refer to interior mutable data
129-
.label = this borrow of an interior mutable value may end up in the final value
127+
const_eval_interior_mutable_borrow_escaping =
128+
shared borrows of lifetime-extended temporaries with interior mutability are not allowed in {const_eval_const_context}s
129+
.label = this borrow of an interior mutable value refers to a lifetime-extended temporary
130130
.help = to fix this, the value can be extracted to a separate `static` item and then referenced
131131
.teach_note =
132-
References that escape into the final value of a constant or static must be immutable.
132+
This creates a raw pointer to a temporary that has its lifetime extended to last for the entire program.
133+
Lifetime-extended temporaries in constants and statics must be immutable.
133134
This is to avoid accidentally creating shared mutable state.
134135
135136
@@ -215,19 +216,11 @@ const_eval_modified_global =
215216
216217
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
217218
218-
const_eval_mutable_raw_escaping =
219-
raw mutable pointers are not allowed in the final value of {const_eval_const_context}s
219+
const_eval_mutable_borrow_escaping =
220+
mutable borrows of lifetime-extended temporaries are not allowed in {const_eval_const_context}s
220221
.teach_note =
221-
Pointers that escape into the final value of a constant or static must be immutable.
222-
This is to avoid accidentally creating shared mutable state.
223-
224-
225-
If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
226-
227-
const_eval_mutable_ref_escaping =
228-
mutable references are not allowed in the final value of {const_eval_const_context}s
229-
.teach_note =
230-
References that escape into the final value of a constant or static must be immutable.
222+
This creates a reference to a temporary that has its lifetime extended to last for the entire program.
223+
Lifetime-extended temporaries in constants and statics must be immutable.
231224
This is to avoid accidentally creating shared mutable state.
232225
233226

compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -602,11 +602,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
602602
self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut);
603603

604604
if !is_allowed && self.place_may_escape(place) {
605-
self.check_op(ops::EscapingMutBorrow(if matches!(rvalue, Rvalue::Ref(..)) {
606-
hir::BorrowKind::Ref
607-
} else {
608-
hir::BorrowKind::Raw
609-
}));
605+
self.check_op(ops::EscapingMutBorrow);
610606
}
611607
}
612608

compiler/rustc_const_eval/src/check_consts/ops.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow {
583583
DiagImportance::Secondary
584584
}
585585
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
586-
ccx.dcx().create_err(errors::InteriorMutableRefEscaping {
586+
ccx.dcx().create_err(errors::InteriorMutableBorrowEscaping {
587587
span,
588588
opt_help: matches!(ccx.const_kind(), hir::ConstContext::Static(_)),
589589
kind: ccx.const_kind(),
@@ -596,7 +596,7 @@ impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow {
596596
/// This op is for `&mut` borrows in the trailing expression of a constant
597597
/// which uses the "enclosing scopes rule" to leak its locals into anonymous
598598
/// static or const items.
599-
pub(crate) struct EscapingMutBorrow(pub hir::BorrowKind);
599+
pub(crate) struct EscapingMutBorrow;
600600

601601
impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow {
602602
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
@@ -610,18 +610,11 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow {
610610
}
611611

612612
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
613-
match self.0 {
614-
hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::MutableRawEscaping {
615-
span,
616-
kind: ccx.const_kind(),
617-
teach: ccx.tcx.sess.teach(E0764),
618-
}),
619-
hir::BorrowKind::Ref => ccx.dcx().create_err(errors::MutableRefEscaping {
620-
span,
621-
kind: ccx.const_kind(),
622-
teach: ccx.tcx.sess.teach(E0764),
623-
}),
624-
}
613+
ccx.dcx().create_err(errors::MutableBorrowEscaping {
614+
span,
615+
kind: ccx.const_kind(),
616+
teach: ccx.tcx.sess.teach(E0764),
617+
})
625618
}
626619
}
627620

compiler/rustc_const_eval/src/errors.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -152,24 +152,15 @@ pub(crate) struct UnmarkedIntrinsicExposed {
152152
}
153153

154154
#[derive(Diagnostic)]
155-
#[diag(const_eval_mutable_ref_escaping, code = E0764)]
156-
pub(crate) struct MutableRefEscaping {
155+
#[diag(const_eval_mutable_borrow_escaping, code = E0764)]
156+
pub(crate) struct MutableBorrowEscaping {
157157
#[primary_span]
158158
pub span: Span,
159159
pub kind: ConstContext,
160160
#[note(const_eval_teach_note)]
161161
pub teach: bool,
162162
}
163163

164-
#[derive(Diagnostic)]
165-
#[diag(const_eval_mutable_raw_escaping, code = E0764)]
166-
pub(crate) struct MutableRawEscaping {
167-
#[primary_span]
168-
pub span: Span,
169-
pub kind: ConstContext,
170-
#[note(const_eval_teach_note)]
171-
pub teach: bool,
172-
}
173164
#[derive(Diagnostic)]
174165
#[diag(const_eval_non_const_fmt_macro_call, code = E0015)]
175166
pub(crate) struct NonConstFmtMacroCall {
@@ -227,8 +218,8 @@ pub(crate) struct UnallowedInlineAsm {
227218
}
228219

229220
#[derive(Diagnostic)]
230-
#[diag(const_eval_interior_mutable_ref_escaping, code = E0492)]
231-
pub(crate) struct InteriorMutableRefEscaping {
221+
#[diag(const_eval_interior_mutable_borrow_escaping, code = E0492)]
222+
pub(crate) struct InteriorMutableBorrowEscaping {
232223
#[primary_span]
233224
#[label]
234225
pub span: Span,

tests/ui/consts/const-mut-refs/issue-76510.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::mem::{transmute, ManuallyDrop};
22

33
const S: &'static mut str = &mut " hello ";
4-
//~^ ERROR: mutable references are not allowed in the final value of constants
4+
//~^ ERROR: mutable borrows of lifetime-extended temporaries
55

66
const fn trigger() -> [(); unsafe {
77
let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));

tests/ui/consts/const-mut-refs/issue-76510.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0764]: mutable references are not allowed in the final value of constants
1+
error[E0764]: mutable borrows of lifetime-extended temporaries are not allowed in constants
22
--> $DIR/issue-76510.rs:3:29
33
|
44
LL | const S: &'static mut str = &mut " hello ";

tests/ui/consts/const-mut-refs/mut_ref_in_final.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const A: *const i32 = &4;
1212
// It could be made sound to allow it to compile,
1313
// but we do not want to allow this to compile,
1414
// as that would be an enormous footgun in oli-obk's opinion.
15-
const B: *mut i32 = &mut 4; //~ ERROR mutable references are not allowed
15+
const B: *mut i32 = &mut 4; //~ ERROR mutable borrows of lifetime-extended temporaries
1616

1717
// Ok, no actual mutable allocation exists
1818
const B2: Option<&mut i32> = None;
@@ -29,7 +29,7 @@ const IMMUT_MUT_REF: &mut u16 = unsafe { mem::transmute(&13) };
2929
static IMMUT_MUT_REF_STATIC: &mut u16 = unsafe { mem::transmute(&13) };
3030
//~^ ERROR pointing to read-only memory
3131

32-
// Ok, because no references to mutable data exist here, since the `{}` moves
32+
// Ok, because no borrows of mutable data exist here, since the `{}` moves
3333
// its value and then takes a reference to that.
3434
const C: *const i32 = &{
3535
let mut x = 42;
@@ -69,13 +69,13 @@ unsafe impl<T> Sync for SyncPtr<T> {}
6969
// (This relies on `SyncPtr` being a curly brace struct.)
7070
// However, we intern the inner memory as read-only, so this must be rejected.
7171
static RAW_MUT_CAST_S: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
72-
//~^ ERROR mutable references are not allowed
72+
//~^ ERROR mutable borrows of lifetime-extended temporaries
7373
static RAW_MUT_COERCE_S: SyncPtr<i32> = SyncPtr { x: &mut 0 };
74-
//~^ ERROR mutable references are not allowed
74+
//~^ ERROR mutable borrows of lifetime-extended temporaries
7575
const RAW_MUT_CAST_C: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
76-
//~^ ERROR mutable references are not allowed
76+
//~^ ERROR mutable borrows of lifetime-extended temporaries
7777
const RAW_MUT_COERCE_C: SyncPtr<i32> = SyncPtr { x: &mut 0 };
78-
//~^ ERROR mutable references are not allowed
78+
//~^ ERROR mutable borrows of lifetime-extended temporaries
7979

8080
fn main() {
8181
println!("{}", unsafe { *A });

tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0764]: mutable references are not allowed in the final value of constants
1+
error[E0764]: mutable borrows of lifetime-extended temporaries are not allowed in constants
22
--> $DIR/mut_ref_in_final.rs:15:21
33
|
44
LL | const B: *mut i32 = &mut 4;
@@ -76,25 +76,25 @@ LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42));
7676
| | creates a temporary value which is freed while still in use
7777
| using this value as a static requires that borrow lasts for `'static`
7878

79-
error[E0764]: mutable references are not allowed in the final value of statics
79+
error[E0764]: mutable borrows of lifetime-extended temporaries are not allowed in statics
8080
--> $DIR/mut_ref_in_final.rs:71:53
8181
|
8282
LL | static RAW_MUT_CAST_S: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
8383
| ^^^^^^^
8484

85-
error[E0764]: mutable references are not allowed in the final value of statics
85+
error[E0764]: mutable borrows of lifetime-extended temporaries are not allowed in statics
8686
--> $DIR/mut_ref_in_final.rs:73:54
8787
|
8888
LL | static RAW_MUT_COERCE_S: SyncPtr<i32> = SyncPtr { x: &mut 0 };
8989
| ^^^^^^
9090

91-
error[E0764]: mutable references are not allowed in the final value of constants
91+
error[E0764]: mutable borrows of lifetime-extended temporaries are not allowed in constants
9292
--> $DIR/mut_ref_in_final.rs:75:52
9393
|
9494
LL | const RAW_MUT_CAST_C: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
9595
| ^^^^^^^
9696

97-
error[E0764]: mutable references are not allowed in the final value of constants
97+
error[E0764]: mutable borrows of lifetime-extended temporaries are not allowed in constants
9898
--> $DIR/mut_ref_in_final.rs:77:53
9999
|
100100
LL | const RAW_MUT_COERCE_C: SyncPtr<i32> = SyncPtr { x: &mut 0 };

tests/ui/consts/const-promoted-opaque.atomic.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ LL |
77
LL | };
88
| - value is dropped here
99

10-
error[E0492]: constants cannot refer to interior mutable data
10+
error[E0492]: shared borrows of lifetime-extended temporaries with interior mutability are not allowed in constants
1111
--> $DIR/const-promoted-opaque.rs:36:19
1212
|
1313
LL | const BAZ: &Foo = &FOO;
14-
| ^^^^ this borrow of an interior mutable value may end up in the final value
14+
| ^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary
1515

1616
error[E0716]: temporary value dropped while borrowed
1717
--> $DIR/const-promoted-opaque.rs:40:26

tests/ui/consts/const-promoted-opaque.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const BAR: () = {
3434
};
3535

3636
const BAZ: &Foo = &FOO;
37-
//[atomic]~^ ERROR: constants cannot refer to interior mutable data
37+
//[atomic]~^ ERROR: shared borrows of lifetime-extended temporaries with interior mutability
3838

3939
fn main() {
4040
let _: &'static _ = &FOO;

tests/ui/consts/issue-17718-const-bad-values.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#![allow(static_mut_refs)]
66

77
const C1: &'static mut [usize] = &mut [];
8-
//~^ ERROR: mutable references are not allowed
8+
//~^ ERROR: mutable borrows of lifetime-extended temporaries
99

1010
static mut S: i32 = 3;
1111
const C2: &'static mut i32 = unsafe { &mut S };

tests/ui/consts/issue-17718-const-bad-values.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0764]: mutable references are not allowed in the final value of constants
1+
error[E0764]: mutable borrows of lifetime-extended temporaries are not allowed in constants
22
--> $DIR/issue-17718-const-bad-values.rs:7:34
33
|
44
LL | const C1: &'static mut [usize] = &mut [];

tests/ui/consts/issue-17718-const-borrow.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ use std::cell::UnsafeCell;
22

33
const A: UnsafeCell<usize> = UnsafeCell::new(1);
44
const B: &'static UnsafeCell<usize> = &A;
5-
//~^ ERROR: cannot refer to interior mutable
5+
//~^ ERROR: shared borrows of lifetime-extended temporaries with interior mutability
66

77
struct C { a: UnsafeCell<usize> }
88
const D: C = C { a: UnsafeCell::new(1) };
99
const E: &'static UnsafeCell<usize> = &D.a;
10-
//~^ ERROR: cannot refer to interior mutable
10+
//~^ ERROR: shared borrows of lifetime-extended temporaries with interior mutability
1111
const F: &'static C = &D;
12-
//~^ ERROR: cannot refer to interior mutable
12+
//~^ ERROR: shared borrows of lifetime-extended temporaries with interior mutability
1313

1414
fn main() {}

tests/ui/consts/issue-17718-const-borrow.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
error[E0492]: constants cannot refer to interior mutable data
1+
error[E0492]: shared borrows of lifetime-extended temporaries with interior mutability are not allowed in constants
22
--> $DIR/issue-17718-const-borrow.rs:4:39
33
|
44
LL | const B: &'static UnsafeCell<usize> = &A;
5-
| ^^ this borrow of an interior mutable value may end up in the final value
5+
| ^^ this borrow of an interior mutable value refers to a lifetime-extended temporary
66

7-
error[E0492]: constants cannot refer to interior mutable data
7+
error[E0492]: shared borrows of lifetime-extended temporaries with interior mutability are not allowed in constants
88
--> $DIR/issue-17718-const-borrow.rs:9:39
99
|
1010
LL | const E: &'static UnsafeCell<usize> = &D.a;
11-
| ^^^^ this borrow of an interior mutable value may end up in the final value
11+
| ^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary
1212

13-
error[E0492]: constants cannot refer to interior mutable data
13+
error[E0492]: shared borrows of lifetime-extended temporaries with interior mutability are not allowed in constants
1414
--> $DIR/issue-17718-const-borrow.rs:11:23
1515
|
1616
LL | const F: &'static C = &D;
17-
| ^^ this borrow of an interior mutable value may end up in the final value
17+
| ^^ this borrow of an interior mutable value refers to a lifetime-extended temporary
1818

1919
error: aborting due to 3 previous errors
2020

tests/ui/consts/partial_qualif.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::cell::Cell;
33
const FOO: &(Cell<usize>, bool) = {
44
let mut a = (Cell::new(0), false);
55
a.1 = true; // sets `qualif(a)` to `qualif(a) | qualif(true)`
6-
&{a} //~ ERROR cannot refer to interior mutable
6+
&{a} //~ ERROR shared borrows of lifetime-extended temporaries with interior mutability
77
};
88

99
fn main() {}

tests/ui/consts/partial_qualif.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0492]: constants cannot refer to interior mutable data
1+
error[E0492]: shared borrows of lifetime-extended temporaries with interior mutability are not allowed in constants
22
--> $DIR/partial_qualif.rs:6:5
33
|
44
LL | &{a}
5-
| ^^^^ this borrow of an interior mutable value may end up in the final value
5+
| ^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary
66

77
error: aborting due to 1 previous error
88

tests/ui/consts/qualif_overwrite.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::cell::Cell;
77
const FOO: &Option<Cell<usize>> = {
88
let mut a = Some(Cell::new(0));
99
a = None; // sets `qualif(a)` to `qualif(a) | qualif(None)`
10-
&{a} //~ ERROR cannot refer to interior mutable
10+
&{a} //~ ERROR shared borrows of lifetime-extended temporaries with interior mutability
1111
};
1212

1313
fn main() {}

tests/ui/consts/qualif_overwrite.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0492]: constants cannot refer to interior mutable data
1+
error[E0492]: shared borrows of lifetime-extended temporaries with interior mutability are not allowed in constants
22
--> $DIR/qualif_overwrite.rs:10:5
33
|
44
LL | &{a}
5-
| ^^^^ this borrow of an interior mutable value may end up in the final value
5+
| ^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary
66

77
error: aborting due to 1 previous error
88

tests/ui/consts/qualif_overwrite_2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::cell::Cell;
55
const FOO: &Option<Cell<usize>> = {
66
let mut a = (Some(Cell::new(0)),);
77
a.0 = None; // sets `qualif(a)` to `qualif(a) | qualif(None)`
8-
&{a.0} //~ ERROR cannot refer to interior mutable
8+
&{a.0} //~ ERROR shared borrows of lifetime-extended temporaries with interior mutability
99
};
1010

1111
fn main() {}

tests/ui/consts/qualif_overwrite_2.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0492]: constants cannot refer to interior mutable data
1+
error[E0492]: shared borrows of lifetime-extended temporaries with interior mutability are not allowed in constants
22
--> $DIR/qualif_overwrite_2.rs:8:5
33
|
44
LL | &{a.0}
5-
| ^^^^^^ this borrow of an interior mutable value may end up in the final value
5+
| ^^^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary
66

77
error: aborting due to 1 previous error
88

tests/ui/consts/refs-to-cell-in-final.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ unsafe impl<T> Sync for SyncPtr<T> {}
1111
// The resulting constant would pass all validation checks, so it is crucial that this gets rejected
1212
// by static const checks!
1313
static RAW_SYNC_S: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
14-
//~^ ERROR: cannot refer to interior mutable data
14+
//~^ ERROR: shared borrows of lifetime-extended temporaries with interior mutability
1515
const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
16-
//~^ ERROR: cannot refer to interior mutable data
16+
//~^ ERROR: shared borrows of lifetime-extended temporaries with interior mutability
1717

1818
// This one does not get promoted because of `Drop`, and then enters interesting codepaths because
1919
// as a value it has no interior mutability, but as a type it does. See
@@ -39,7 +39,7 @@ const NONE_EXPLICIT_PROMOTED: &'static Option<Cell<i32>> = {
3939

4040
// Not okay, since we are borrowing something with interior mutability.
4141
const INTERIOR_MUT_VARIANT: &Option<UnsafeCell<bool>> = &{
42-
//~^ERROR: cannot refer to interior mutable data
42+
//~^ERROR: shared borrows of lifetime-extended temporaries with interior mutability
4343
let mut x = None;
4444
assert!(x.is_none());
4545
x = Some(UnsafeCell::new(false));

0 commit comments

Comments
 (0)