Skip to content

Commit 8939a10

Browse files
committed
clarify and unify 'transient mutable borrow' errors
1 parent 8fc76db commit 8939a10

31 files changed

+83
-110
lines changed

compiler/rustc_const_eval/messages.ftl

Lines changed: 10 additions & 17 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+
interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a {const_eval_const_context} are not allowed
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
@@ -213,25 +214,17 @@ const_eval_memory_exhausted =
213214
const_eval_modified_global =
214215
modifying a static's initial value from another static's initializer
215216
216-
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
217-
218-
const_eval_mutable_raw_escaping =
219-
raw mutable pointers are not allowed in the final value of {const_eval_const_context}s
217+
const_eval_mutable_borrow_escaping =
218+
mutable borrows of lifetime-extended temporaries in the top-level scope of a {const_eval_const_context} are not allowed
220219
.teach_note =
221-
Pointers that escape into the final value of a constant or static must be immutable.
220+
This creates a reference to a temporary that has its lifetime extended to last for the entire program.
221+
Lifetime-extended temporaries in constants and statics must be immutable.
222222
This is to avoid accidentally creating shared mutable state.
223223
224224
225225
If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
226226
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.
231-
This is to avoid accidentally creating shared mutable state.
232-
233-
234-
If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
227+
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
235228
236229
const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead
237230

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 in the top-level scope of a constant are not allowed
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: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ 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;
1919

2020
// Not ok, can't prove that no mutable allocation ends up in final value
21-
const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR mutable references are not allowed
21+
const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR mutable borrows of lifetime-extended temporaries
2222

2323
const fn helper(x: &mut i32) -> Option<&mut i32> { Some(x) }
2424
const B4: Option<&mut i32> = helper(&mut 42); //~ ERROR temporary value dropped while borrowed
@@ -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: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0764]: mutable references are not allowed in the final value of constants
1+
error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed
22
--> $DIR/mut_ref_in_final.rs:15:21
33
|
44
LL | const B: *mut i32 = &mut 4;
55
| ^^^^^^
66

7-
error[E0764]: mutable references are not allowed in the final value of constants
7+
error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed
88
--> $DIR/mut_ref_in_final.rs:21:35
99
|
1010
LL | const B3: Option<&mut i32> = Some(&mut 42);
@@ -72,25 +72,25 @@ LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42));
7272
| | creates a temporary value which is freed while still in use
7373
| using this value as a static requires that borrow lasts for `'static`
7474

75-
error[E0764]: mutable references are not allowed in the final value of statics
75+
error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a static are not allowed
7676
--> $DIR/mut_ref_in_final.rs:71:53
7777
|
7878
LL | static RAW_MUT_CAST_S: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
7979
| ^^^^^^^
8080

81-
error[E0764]: mutable references are not allowed in the final value of statics
81+
error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a static are not allowed
8282
--> $DIR/mut_ref_in_final.rs:73:54
8383
|
8484
LL | static RAW_MUT_COERCE_S: SyncPtr<i32> = SyncPtr { x: &mut 0 };
8585
| ^^^^^^
8686

87-
error[E0764]: mutable references are not allowed in the final value of constants
87+
error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed
8888
--> $DIR/mut_ref_in_final.rs:75:52
8989
|
9090
LL | const RAW_MUT_CAST_C: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
9191
| ^^^^^^^
9292

93-
error[E0764]: mutable references are not allowed in the final value of constants
93+
error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed
9494
--> $DIR/mut_ref_in_final.rs:77:53
9595
|
9696
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]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed
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: interior mutable shared borrows of lifetime-extended temporaries
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 in the top-level scope of a constant are not allowed
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: interior mutable shared borrows of lifetime-extended temporaries
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: interior mutable shared borrows of lifetime-extended temporaries
1111
const F: &'static C = &D;
12-
//~^ ERROR: cannot refer to interior mutable
12+
//~^ ERROR: interior mutable shared borrows of lifetime-extended temporaries
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]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed
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]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed
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]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed
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 interior mutable shared borrows of lifetime-extended temporaries
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]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed
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 interior mutable shared borrows of lifetime-extended temporaries
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]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed
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 interior mutable shared borrows of lifetime-extended temporaries
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]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed
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

0 commit comments

Comments
 (0)