Skip to content

Commit 2bd35c0

Browse files
authored
Rollup merge of rust-lang#66606 - christianpoveda:mut-refs-in-const-fn, r=oli-obk
Add feature gate for mut refs in const fn r? @oli-obk
2 parents ae1b871 + e01ad6a commit 2bd35c0

33 files changed

+310
-141
lines changed

src/librustc_error_codes/error_codes.rs

-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ E0010: include_str!("./error_codes/E0010.md"),
1818
E0013: include_str!("./error_codes/E0013.md"),
1919
E0014: include_str!("./error_codes/E0014.md"),
2020
E0015: include_str!("./error_codes/E0015.md"),
21-
E0017: include_str!("./error_codes/E0017.md"),
2221
E0019: include_str!("./error_codes/E0019.md"),
2322
E0023: include_str!("./error_codes/E0023.md"),
2423
E0025: include_str!("./error_codes/E0025.md"),

src/librustc_error_codes/error_codes/E0017.md

-20
This file was deleted.

src/librustc_feature/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,9 @@ declare_features! (
523523
/// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
524524
(active, cfg_sanitize, "1.41.0", Some(39699), None),
525525

526+
/// Allows using `&mut` in constant functions.
527+
(active, const_mut_refs, "1.41.0", Some(57349), None),
528+
526529
// -------------------------------------------------------------------------
527530
// feature-group-end: actual feature gates
528531
// -------------------------------------------------------------------------

src/librustc_mir/transform/check_consts/ops.rs

+39-25
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Concrete error types for all operations which may be invalid in a certain const context.
22
33
use rustc::hir::def_id::DefId;
4-
use rustc::mir::BorrowKind;
54
use rustc::session::config::nightly_options;
65
use rustc::ty::TyCtxt;
76
use syntax::feature_gate::feature_err;
@@ -181,38 +180,53 @@ impl NonConstOp for Loop {
181180
}
182181

183182
#[derive(Debug)]
184-
pub struct MutBorrow(pub BorrowKind);
183+
pub struct CellBorrow;
184+
impl NonConstOp for CellBorrow {
185+
fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
186+
span_err!(item.tcx.sess, span, E0492,
187+
"cannot borrow a constant which may contain \
188+
interior mutability, create a static instead");
189+
}
190+
}
191+
192+
#[derive(Debug)]
193+
pub struct MutBorrow;
185194
impl NonConstOp for MutBorrow {
195+
fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
196+
Some(tcx.features().const_mut_refs)
197+
}
198+
186199
fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
187-
let kind = self.0;
188-
if let BorrowKind::Mut { .. } = kind {
189-
let mut err = struct_span_err!(item.tcx.sess, span, E0017,
190-
"references in {}s may only refer \
191-
to immutable values", item.const_kind());
192-
err.span_label(span, format!("{}s require immutable values",
193-
item.const_kind()));
194-
if item.tcx.sess.teach(&err.get_code().unwrap()) {
195-
err.note("References in statics and constants may only refer \
196-
to immutable values.\n\n\
197-
Statics are shared everywhere, and if they refer to \
198-
mutable data one might violate memory safety since \
199-
holding multiple mutable references to shared data \
200-
is not allowed.\n\n\
201-
If you really want global mutable state, try using \
202-
static mut or a global UnsafeCell.");
203-
}
204-
err.emit();
205-
} else {
206-
span_err!(item.tcx.sess, span, E0492,
207-
"cannot borrow a constant which may contain \
208-
interior mutability, create a static instead");
200+
let mut err = feature_err(
201+
&item.tcx.sess.parse_sess,
202+
sym::const_mut_refs,
203+
span,
204+
&format!("references in {}s may only refer \
205+
to immutable values", item.const_kind())
206+
);
207+
err.span_label(span, format!("{}s require immutable values",
208+
item.const_kind()));
209+
if item.tcx.sess.teach(&err.get_code().unwrap()) {
210+
err.note("References in statics and constants may only refer \
211+
to immutable values.\n\n\
212+
Statics are shared everywhere, and if they refer to \
213+
mutable data one might violate memory safety since \
214+
holding multiple mutable references to shared data \
215+
is not allowed.\n\n\
216+
If you really want global mutable state, try using \
217+
static mut or a global UnsafeCell.");
209218
}
219+
err.emit();
210220
}
211221
}
212222

213223
#[derive(Debug)]
214224
pub struct MutDeref;
215-
impl NonConstOp for MutDeref {}
225+
impl NonConstOp for MutDeref {
226+
fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
227+
Some(tcx.features().const_mut_refs)
228+
}
229+
}
216230

217231
#[derive(Debug)]
218232
pub struct Panic;

src/librustc_mir/transform/check_consts/validation.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,11 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
359359
};
360360

361361
if !is_allowed {
362-
self.check_op(ops::MutBorrow(kind));
362+
if let BorrowKind::Mut{ .. } = kind {
363+
self.check_op(ops::MutBorrow);
364+
} else {
365+
self.check_op(ops::CellBorrow);
366+
}
363367
}
364368
}
365369

@@ -384,7 +388,11 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
384388
);
385389

386390
if borrowed_place_has_mut_interior {
387-
self.check_op(ops::MutBorrow(kind));
391+
if let BorrowKind::Mut{ .. } = kind {
392+
self.check_op(ops::MutBorrow);
393+
} else {
394+
self.check_op(ops::CellBorrow);
395+
}
388396
}
389397
}
390398

@@ -451,7 +459,6 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
451459
}
452460
}
453461
}
454-
455462
fn visit_projection_elem(
456463
&mut self,
457464
place_base: &PlaceBase<'tcx>,

src/librustc_mir/transform/qualify_min_const_fn.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,14 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
7979
fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult {
8080
for ty in ty.walk() {
8181
match ty.kind {
82-
ty::Ref(_, _, hir::Mutability::Mutable) => return Err((
83-
span,
84-
"mutable references in const fn are unstable".into(),
85-
)),
82+
ty::Ref(_, _, hir::Mutability::Mutable) => {
83+
if !tcx.features().const_mut_refs {
84+
return Err((
85+
span,
86+
"mutable references in const fn are unstable".into(),
87+
))
88+
}
89+
}
8690
ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
8791
ty::FnPtr(..) => {
8892
if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {

src/libsyntax_pos/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ symbols! {
213213
const_indexing,
214214
const_in_array_repeat_expressions,
215215
const_let,
216+
const_mut_refs,
216217
const_panic,
217218
const_raw_ptr_deref,
218219
const_raw_ptr_to_usize_cast,

src/test/compile-fail/consts/const-fn-error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const fn f(x: usize) -> usize {
66
let mut sum = 0;
77
for i in 0..x {
88
//~^ ERROR E0015
9-
//~| ERROR E0017
9+
//~| ERROR E0658
1010
//~| ERROR E0080
1111
//~| ERROR E0744
1212
//~| ERROR E0019
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
error[E0017]: references in statics may only refer to immutable values
1+
error[E0658]: references in statics may only refer to immutable values
22
--> $DIR/check-static-immutable-mut-slices.rs:3:37
33
|
44
LL | static TEST: &'static mut [isize] = &mut [];
55
| ^^^^^^^ statics require immutable values
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/57349
8+
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
69

710
error: aborting due to previous error
811

9-
For more information about this error, try `rustc --explain E0017`.
12+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
error[E0017]: references in constants may only refer to immutable values
1+
error[E0658]: references in constants may only refer to immutable values
22
--> $DIR/issue-65394.rs:8:13
33
|
44
LL | let r = &mut x;
55
| ^^^^^^ constants require immutable values
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/57349
8+
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
69

710
error[E0493]: destructors cannot be evaluated at compile-time
811
--> $DIR/issue-65394.rs:7:9
@@ -12,5 +15,5 @@ LL | let mut x = Vec::<i32>::new();
1215

1316
error: aborting due to 2 previous errors
1417

15-
Some errors have detailed explanations: E0017, E0493.
16-
For more information about an error, try `rustc --explain E0017`.
18+
Some errors have detailed explanations: E0493, E0658.
19+
For more information about an error, try `rustc --explain E0493`.
+6-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
error[E0017]: references in constants may only refer to immutable values
1+
error[E0658]: references in constants may only refer to immutable values
22
--> $DIR/const-multi-ref.rs:6:13
33
|
44
LL | let p = &mut a;
55
| ^^^^^^ constants require immutable values
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/57349
8+
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
69

710
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
811
--> $DIR/const-multi-ref.rs:16:13
@@ -12,5 +15,5 @@ LL | let p = &a;
1215

1316
error: aborting due to 2 previous errors
1417

15-
Some errors have detailed explanations: E0017, E0492.
16-
For more information about an error, try `rustc --explain E0017`.
18+
Some errors have detailed explanations: E0492, E0658.
19+
For more information about an error, try `rustc --explain E0492`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// run-pass
2+
3+
#![feature(const_mut_refs)]
4+
5+
struct Foo {
6+
x: usize
7+
}
8+
9+
const fn foo() -> Foo {
10+
Foo { x: 0 }
11+
}
12+
13+
impl Foo {
14+
const fn bar(&mut self) -> usize {
15+
self.x = 1;
16+
self.x
17+
}
18+
19+
}
20+
21+
const fn baz(foo: &mut Foo) -> usize {
22+
let x = &mut foo.x;
23+
*x = 2;
24+
*x
25+
}
26+
27+
const fn bazz(foo: &mut Foo) -> usize {
28+
foo.x = 3;
29+
foo.x
30+
}
31+
32+
fn main() {
33+
let _: [(); foo().bar()] = [(); 1];
34+
let _: [(); baz(&mut foo())] = [(); 2];
35+
let _: [(); bazz(&mut foo())] = [(); 3];
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
foo(&mut 5);
3+
}
4+
5+
const fn foo(x: &mut i32) -> i32 { //~ ERROR mutable references in const fn are unstable
6+
*x + 1
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0723]: mutable references in const fn are unstable
2+
--> $DIR/feature-gate-const_mut_refs.rs:5:14
3+
|
4+
LL | const fn foo(x: &mut i32) -> i32 {
5+
| ^
6+
|
7+
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
8+
= help: add `#![feature(const_fn)]` to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0723`.

src/test/ui/consts/const_let_assign3.stderr

+10-4
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,23 @@ error[E0019]: constant function contains unimplemented expression type
44
LL | self.state = x;
55
| ^^^^^^^^^^^^^^
66

7-
error[E0017]: references in constants may only refer to immutable values
7+
error[E0658]: references in constants may only refer to immutable values
88
--> $DIR/const_let_assign3.rs:16:5
99
|
1010
LL | s.foo(3);
1111
| ^ constants require immutable values
12+
|
13+
= note: for more information, see https://github.com/rust-lang/rust/issues/57349
14+
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
1215

13-
error[E0017]: references in constants may only refer to immutable values
16+
error[E0658]: references in constants may only refer to immutable values
1417
--> $DIR/const_let_assign3.rs:22:13
1518
|
1619
LL | let y = &mut x;
1720
| ^^^^^^ constants require immutable values
21+
|
22+
= note: for more information, see https://github.com/rust-lang/rust/issues/57349
23+
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
1824

1925
error[E0019]: constant contains unimplemented expression type
2026
--> $DIR/const_let_assign3.rs:24:5
@@ -24,5 +30,5 @@ LL | *y = 42;
2430

2531
error: aborting due to 4 previous errors
2632

27-
Some errors have detailed explanations: E0017, E0019.
28-
For more information about an error, try `rustc --explain E0017`.
33+
Some errors have detailed explanations: E0019, E0658.
34+
For more information about an error, try `rustc --explain E0019`.

src/test/ui/consts/miri_unleashed/mutable_const.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// compile-flags: -Zunleash-the-miri-inside-of-you
22

33
#![feature(const_raw_ptr_deref)]
4+
#![feature(const_mut_refs)]
45
#![deny(const_err)]
56

67
use std::cell::UnsafeCell;
@@ -12,9 +13,7 @@ const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
1213
const MUTATING_BEHIND_RAW: () = {
1314
// Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
1415
unsafe {
15-
*MUTABLE_BEHIND_RAW = 99 //~ WARN skipping const checks
16-
//~^ ERROR any use of this value will cause an error
17-
//~^^ tried to modify constant memory
16+
*MUTABLE_BEHIND_RAW = 99 //~ ERROR any use of this value will cause an error
1817
}
1918
};
2019

src/test/ui/consts/miri_unleashed/mutable_const.stderr

+3-10
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,23 @@
11
warning: skipping const checks
2-
--> $DIR/mutable_const.rs:9:38
2+
--> $DIR/mutable_const.rs:10:38
33
|
44
LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
55
| ^^^^^^^^^^^^^^^^^^^^
66

7-
warning: skipping const checks
8-
--> $DIR/mutable_const.rs:15:9
9-
|
10-
LL | *MUTABLE_BEHIND_RAW = 99
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^
12-
137
error: any use of this value will cause an error
14-
--> $DIR/mutable_const.rs:15:9
8+
--> $DIR/mutable_const.rs:16:9
159
|
1610
LL | / const MUTATING_BEHIND_RAW: () = {
1711
LL | | // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
1812
LL | | unsafe {
1913
LL | | *MUTABLE_BEHIND_RAW = 99
2014
| | ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory
21-
... |
2215
LL | | }
2316
LL | | };
2417
| |__-
2518
|
2619
note: lint level defined here
27-
--> $DIR/mutable_const.rs:4:9
20+
--> $DIR/mutable_const.rs:5:9
2821
|
2922
LL | #![deny(const_err)]
3023
| ^^^^^^^^^

0 commit comments

Comments
 (0)