From 0b841846ba467f0fe4ec1ee152414e3ae8f7d88e Mon Sep 17 00:00:00 2001 From: oli Date: Sun, 27 Dec 2020 17:33:56 +0000 Subject: [PATCH 01/13] Allow references to interior mutable data behind a feature gate --- .../src/error_codes/E0492.md | 6 ++-- compiler/rustc_feature/src/active.rs | 3 ++ .../src/transform/check_consts/ops.rs | 20 +++++++++++ .../src/transform/check_consts/validation.rs | 34 ++++++++++++++++++- compiler/rustc_span/src/symbol.rs | 1 + .../const-address-of-interior-mut.stderr | 22 +++++++++--- src/test/ui/consts/const-multi-ref.rs | 2 +- src/test/ui/consts/const-multi-ref.stderr | 9 +++-- src/test/ui/consts/partial_qualif.rs | 2 ++ src/test/ui/consts/partial_qualif.stderr | 2 +- src/test/ui/consts/qualif_overwrite.rs | 4 ++- src/test/ui/consts/qualif_overwrite.stderr | 2 +- src/test/ui/consts/qualif_overwrite_2.rs | 2 ++ src/test/ui/consts/qualif_overwrite_2.stderr | 2 +- src/test/ui/consts/std/cell.rs | 13 +++++-- src/test/ui/consts/std/cell.stderr | 27 ++++++++++----- src/test/ui/error-codes/E0492.rs | 7 +++- src/test/ui/error-codes/E0492.stderr | 12 +++++-- .../feature-gate-const_refs_to_cell.rs | 12 +++++++ .../ui/issues/issue-17718-const-borrow.rs | 8 +++-- .../ui/issues/issue-17718-const-borrow.stderr | 6 ++-- src/test/ui/unsafe/ranged_ints3_const.rs | 4 +-- src/test/ui/unsafe/ranged_ints3_const.stderr | 12 +++++-- 23 files changed, 171 insertions(+), 41 deletions(-) create mode 100644 src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs diff --git a/compiler/rustc_error_codes/src/error_codes/E0492.md b/compiler/rustc_error_codes/src/error_codes/E0492.md index 1caa59999ae..30235b0aeb0 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0492.md +++ b/compiler/rustc_error_codes/src/error_codes/E0492.md @@ -3,10 +3,11 @@ A borrow of a constant containing interior mutability was attempted. Erroneous code example: ```compile_fail,E0492 +#![feature(const_refs_to_cell)] use std::sync::atomic::AtomicUsize; const A: AtomicUsize = AtomicUsize::new(0); -static B: &'static AtomicUsize = &A; +const B: &'static AtomicUsize = &A; // error: cannot borrow a constant which may contain interior mutability, // create a static instead ``` @@ -18,7 +19,7 @@ can't be changed via a shared `&` pointer, but interior mutability would allow it. That is, a constant value could be mutated. On the other hand, a `static` is explicitly a single memory location, which can be mutated at will. -So, in order to solve this error, either use statics which are `Sync`: +So, in order to solve this error, use statics which are `Sync`: ``` use std::sync::atomic::AtomicUsize; @@ -30,6 +31,7 @@ static B: &'static AtomicUsize = &A; // ok! You can also have this error while using a cell type: ```compile_fail,E0492 +#![feature(const_refs_to_cell)] use std::cell::Cell; const A: Cell = Cell::new(1); diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 252e96b47c6..3b54ffbc3f0 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -626,6 +626,9 @@ declare_features! ( /// Allows const generics to have default values (e.g. `struct Foo(...);`). (active, const_generics_defaults, "1.51.0", Some(44580), None), + /// Allows references to types with interior mutability within constants + (active, const_refs_to_cell, "1.51.0", Some(80384), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index d2e65abfbc7..1ee6615f6f0 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -208,9 +208,29 @@ impl NonConstOp for LiveDrop { } } +#[derive(Debug)] +pub struct CellBorrowBehindRef; +impl NonConstOp for CellBorrowBehindRef { + fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status { + Status::Unstable(sym::const_refs_to_cell) + } + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_refs_to_cell, + span, + "cannot borrow here, since the borrowed element may contain interior mutability", + ) + } +} + #[derive(Debug)] pub struct CellBorrow; impl NonConstOp for CellBorrow { + fn importance(&self) -> DiagnosticImportance { + // The problematic cases will already emit a `CellBorrowBehindRef` + DiagnosticImportance::Secondary + } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { struct_span_err!( ccx.tcx.sess, diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 90688ebbd0a..8830575f189 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -3,6 +3,7 @@ use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorReported}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId, LangItem}; +use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; @@ -188,6 +189,9 @@ pub struct Validator<'mir, 'tcx> { /// The span of the current statement. span: Span, + /// A set that stores for each local whether it has a `StorageDead` for it somewhere. + local_has_storage_dead: Option>, + error_emitted: Option, secondary_errors: Vec, } @@ -206,6 +210,7 @@ impl Validator<'mir, 'tcx> { span: ccx.body.span, ccx, qualifs: Default::default(), + local_has_storage_dead: None, error_emitted: None, secondary_errors: Vec::new(), } @@ -282,6 +287,27 @@ impl Validator<'mir, 'tcx> { } } + fn local_has_storage_dead(&mut self, local: Local) -> bool { + let ccx = self.ccx; + self.local_has_storage_dead + .get_or_insert_with(|| { + struct StorageDeads { + locals: BitSet, + } + impl Visitor<'tcx> for StorageDeads { + fn visit_statement(&mut self, stmt: &Statement<'tcx>, _: Location) { + if let StatementKind::StorageDead(l) = stmt.kind { + self.locals.insert(l); + } + } + } + let mut v = StorageDeads { locals: BitSet::new_empty(ccx.body.local_decls.len()) }; + v.visit_body(ccx.body); + v.locals + }) + .contains(local) + } + pub fn qualifs_in_return_place(&mut self) -> ConstQualifs { self.qualifs.in_return_place(self.ccx, self.error_emitted) } @@ -556,7 +582,13 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { ); if borrowed_place_has_mut_interior { - self.check_op(ops::CellBorrow); + // Locals without StorageDead follow the "trailing expression" rule, meaning + // they are essentially anonymous static items themselves. + if self.local_has_storage_dead(place.local) { + self.check_op(ops::CellBorrowBehindRef); + } else { + self.check_op(ops::CellBorrow); + } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 64b50a9b70a..b6cf584d875 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -381,6 +381,7 @@ symbols! { const_ptr, const_raw_ptr_deref, const_raw_ptr_to_usize_cast, + const_refs_to_cell, const_slice_ptr, const_trait_bound_opt_out, const_trait_impl, diff --git a/src/test/ui/consts/const-address-of-interior-mut.stderr b/src/test/ui/consts/const-address-of-interior-mut.stderr index f15174c33b3..93120753b1a 100644 --- a/src/test/ui/consts/const-address-of-interior-mut.stderr +++ b/src/test/ui/consts/const-address-of-interior-mut.stderr @@ -1,27 +1,39 @@ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability --> $DIR/const-address-of-interior-mut.rs:5:39 | LL | const A: () = { let x = Cell::new(2); &raw const x; }; | ^^^^^^^^^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability --> $DIR/const-address-of-interior-mut.rs:7:40 | LL | static B: () = { let x = Cell::new(2); &raw const x; }; | ^^^^^^^^^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability --> $DIR/const-address-of-interior-mut.rs:9:44 | LL | static mut C: () = { let x = Cell::new(2); &raw const x; }; | ^^^^^^^^^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability --> $DIR/const-address-of-interior-mut.rs:13:13 | LL | let y = &raw const x; | ^^^^^^^^^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0492`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-multi-ref.rs b/src/test/ui/consts/const-multi-ref.rs index 18645efc887..7e0f1a812fd 100644 --- a/src/test/ui/consts/const-multi-ref.rs +++ b/src/test/ui/consts/const-multi-ref.rs @@ -13,7 +13,7 @@ const _: i32 = { const _: std::cell::Cell = { let mut a = std::cell::Cell::new(5); - let p = &a; //~ ERROR cannot borrow a constant which may contain interior mutability + let p = &a; //~ ERROR borrowed element may contain interior mutability let reborrow = {p}; let pp = &reborrow; diff --git a/src/test/ui/consts/const-multi-ref.stderr b/src/test/ui/consts/const-multi-ref.stderr index 9a7914b4588..c0a320d46cb 100644 --- a/src/test/ui/consts/const-multi-ref.stderr +++ b/src/test/ui/consts/const-multi-ref.stderr @@ -4,13 +4,16 @@ error[E0764]: mutable references are not allowed in constants LL | let p = &mut a; | ^^^^^^ `&mut` is only allowed in `const fn` -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability --> $DIR/const-multi-ref.rs:16:13 | LL | let p = &a; | ^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable error: aborting due to 2 previous errors -Some errors have detailed explanations: E0492, E0764. -For more information about an error, try `rustc --explain E0492`. +Some errors have detailed explanations: E0658, E0764. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/partial_qualif.rs b/src/test/ui/consts/partial_qualif.rs index 32c68e69f4b..e069a023aa1 100644 --- a/src/test/ui/consts/partial_qualif.rs +++ b/src/test/ui/consts/partial_qualif.rs @@ -1,3 +1,5 @@ +#![feature(const_refs_to_cell)] + use std::cell::Cell; const FOO: &(Cell, bool) = { diff --git a/src/test/ui/consts/partial_qualif.stderr b/src/test/ui/consts/partial_qualif.stderr index 221e449b6f9..58acde1b58a 100644 --- a/src/test/ui/consts/partial_qualif.stderr +++ b/src/test/ui/consts/partial_qualif.stderr @@ -1,5 +1,5 @@ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/partial_qualif.rs:6:5 + --> $DIR/partial_qualif.rs:8:5 | LL | &{a} | ^^^^ diff --git a/src/test/ui/consts/qualif_overwrite.rs b/src/test/ui/consts/qualif_overwrite.rs index 430eea37de7..9c20d94c6dd 100644 --- a/src/test/ui/consts/qualif_overwrite.rs +++ b/src/test/ui/consts/qualif_overwrite.rs @@ -1,3 +1,5 @@ +#![feature(const_refs_to_cell)] + use std::cell::Cell; // this is overly conservative. The reset to `None` should clear `a` of all qualifications @@ -7,7 +9,7 @@ use std::cell::Cell; const FOO: &Option> = { let mut a = Some(Cell::new(0)); a = None; // sets `qualif(a)` to `qualif(a) | qualif(None)` - &{a} //~ ERROR cannot borrow a constant which may contain interior mutability + &{a}//~ ERROR cannot borrow a constant which may contain interior mutability }; fn main() {} diff --git a/src/test/ui/consts/qualif_overwrite.stderr b/src/test/ui/consts/qualif_overwrite.stderr index fbaae711d7c..a6c8c599ecc 100644 --- a/src/test/ui/consts/qualif_overwrite.stderr +++ b/src/test/ui/consts/qualif_overwrite.stderr @@ -1,5 +1,5 @@ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/qualif_overwrite.rs:10:5 + --> $DIR/qualif_overwrite.rs:12:5 | LL | &{a} | ^^^^ diff --git a/src/test/ui/consts/qualif_overwrite_2.rs b/src/test/ui/consts/qualif_overwrite_2.rs index fa79b5c14a7..5d0843710e2 100644 --- a/src/test/ui/consts/qualif_overwrite_2.rs +++ b/src/test/ui/consts/qualif_overwrite_2.rs @@ -1,3 +1,5 @@ +#![feature(const_refs_to_cell)] + use std::cell::Cell; // const qualification is not smart enough to know about fields and always assumes that there might diff --git a/src/test/ui/consts/qualif_overwrite_2.stderr b/src/test/ui/consts/qualif_overwrite_2.stderr index a393c4e336d..f109b4cea81 100644 --- a/src/test/ui/consts/qualif_overwrite_2.stderr +++ b/src/test/ui/consts/qualif_overwrite_2.stderr @@ -1,5 +1,5 @@ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/qualif_overwrite_2.rs:8:5 + --> $DIR/qualif_overwrite_2.rs:10:5 | LL | &{a.0} | ^^^^^^ diff --git a/src/test/ui/consts/std/cell.rs b/src/test/ui/consts/std/cell.rs index cf6c0f2379d..ee4df6f43fa 100644 --- a/src/test/ui/consts/std/cell.rs +++ b/src/test/ui/consts/std/cell.rs @@ -1,18 +1,26 @@ +#![feature(const_refs_to_cell)] + use std::cell::*; // not ok, because this would create a silent constant with interior mutability. // the rules could be relaxed in the future static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); -//~^ ERROR cannot borrow a constant which may contain interior mutability +//~^ ERROR encountered dangling pointer +const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); +//~^ ERROR encountered dangling pointer static FOO3: Wrap> = Wrap(Cell::new(42)); +const FOO3_CONST: Wrap> = Wrap(Cell::new(42)); + // ok static FOO4: Wrap<*mut u32> = Wrap(FOO3.0.as_ptr()); +const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr()); +//~^ ERROR encountered dangling pointer // not ok, because the `as_ptr` call takes a reference to a type with interior mutability // which is not allowed in constants const FOO2: *mut u32 = Cell::new(42).as_ptr(); -//~^ ERROR cannot borrow a constant which may contain interior mutability +//~^ ERROR encountered dangling pointer struct IMSafeTrustMe(UnsafeCell); unsafe impl Send for IMSafeTrustMe {} @@ -21,6 +29,7 @@ unsafe impl Sync for IMSafeTrustMe {} static BAR: IMSafeTrustMe = IMSafeTrustMe(UnsafeCell::new(5)); + struct Wrap(T); unsafe impl Send for Wrap {} unsafe impl Sync for Wrap {} diff --git a/src/test/ui/consts/std/cell.stderr b/src/test/ui/consts/std/cell.stderr index f75aadff6d5..75cae00611a 100644 --- a/src/test/ui/consts/std/cell.stderr +++ b/src/test/ui/consts/std/cell.stderr @@ -1,15 +1,26 @@ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/cell.rs:5:35 +error: encountered dangling pointer in final constant + --> $DIR/cell.rs:7:1 | LL | static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/cell.rs:14:24 +error: encountered dangling pointer in final constant + --> $DIR/cell.rs:9:1 + | +LL | const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: encountered dangling pointer in final constant + --> $DIR/cell.rs:17:1 + | +LL | const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: encountered dangling pointer in final constant + --> $DIR/cell.rs:22:1 | LL | const FOO2: *mut u32 = Cell::new(42).as_ptr(); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0492`. diff --git a/src/test/ui/error-codes/E0492.rs b/src/test/ui/error-codes/E0492.rs index 2de4c12eb64..d8357f0c678 100644 --- a/src/test/ui/error-codes/E0492.rs +++ b/src/test/ui/error-codes/E0492.rs @@ -1,7 +1,12 @@ +#![feature(const_refs_to_cell)] + use std::sync::atomic::AtomicUsize; const A: AtomicUsize = AtomicUsize::new(0); -static B: &'static AtomicUsize = &A; //~ ERROR E0492 +const B: &'static AtomicUsize = &A; //~ ERROR E0492 +static C: &'static AtomicUsize = &A; //~ ERROR E0492 + +const NONE: &'static Option = &None; fn main() { } diff --git a/src/test/ui/error-codes/E0492.stderr b/src/test/ui/error-codes/E0492.stderr index 5f337dd7f42..ffc4ff372a3 100644 --- a/src/test/ui/error-codes/E0492.stderr +++ b/src/test/ui/error-codes/E0492.stderr @@ -1,9 +1,15 @@ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/E0492.rs:4:34 + --> $DIR/E0492.rs:6:33 | -LL | static B: &'static AtomicUsize = &A; +LL | const B: &'static AtomicUsize = &A; + | ^^ + +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/E0492.rs:7:34 + | +LL | static C: &'static AtomicUsize = &A; | ^^ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0492`. diff --git a/src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs b/src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs new file mode 100644 index 00000000000..63159ed0553 --- /dev/null +++ b/src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(const_refs_to_cell)] + +const FOO: () = { + let x = std::cell::Cell::new(42); + let y = &x; +}; + +fn main() { + FOO; +} diff --git a/src/test/ui/issues/issue-17718-const-borrow.rs b/src/test/ui/issues/issue-17718-const-borrow.rs index 8a31bd0c66a..7bde2361f61 100644 --- a/src/test/ui/issues/issue-17718-const-borrow.rs +++ b/src/test/ui/issues/issue-17718-const-borrow.rs @@ -1,14 +1,16 @@ +#![feature(const_refs_to_cell)] + use std::cell::UnsafeCell; const A: UnsafeCell = UnsafeCell::new(1); const B: &'static UnsafeCell = &A; -//~^ ERROR: cannot borrow a constant which may contain interior mutability +//~^ ERROR: may contain interior mutability struct C { a: UnsafeCell } const D: C = C { a: UnsafeCell::new(1) }; const E: &'static UnsafeCell = &D.a; -//~^ ERROR: cannot borrow a constant which may contain interior mutability +//~^ ERROR: may contain interior mutability const F: &'static C = &D; -//~^ ERROR: cannot borrow a constant which may contain interior mutability +//~^ ERROR: may contain interior mutability fn main() {} diff --git a/src/test/ui/issues/issue-17718-const-borrow.stderr b/src/test/ui/issues/issue-17718-const-borrow.stderr index b4330049689..1bfb3982bc3 100644 --- a/src/test/ui/issues/issue-17718-const-borrow.stderr +++ b/src/test/ui/issues/issue-17718-const-borrow.stderr @@ -1,17 +1,17 @@ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/issue-17718-const-borrow.rs:4:39 + --> $DIR/issue-17718-const-borrow.rs:6:39 | LL | const B: &'static UnsafeCell = &A; | ^^ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/issue-17718-const-borrow.rs:9:39 + --> $DIR/issue-17718-const-borrow.rs:11:39 | LL | const E: &'static UnsafeCell = &D.a; | ^^^^ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/issue-17718-const-borrow.rs:11:23 + --> $DIR/issue-17718-const-borrow.rs:13:23 | LL | const F: &'static C = &D; | ^^ diff --git a/src/test/ui/unsafe/ranged_ints3_const.rs b/src/test/ui/unsafe/ranged_ints3_const.rs index 7b03d8eda93..c069ae7da02 100644 --- a/src/test/ui/unsafe/ranged_ints3_const.rs +++ b/src/test/ui/unsafe/ranged_ints3_const.rs @@ -9,13 +9,13 @@ fn main() {} const fn foo() -> NonZero> { let mut x = unsafe { NonZero(Cell::new(1)) }; - let y = &x.0; //~ ERROR cannot borrow a constant which may contain interior mutability + let y = &x.0; //~ ERROR the borrowed element may contain interior mutability //~^ ERROR borrow of layout constrained field with interior mutability unsafe { NonZero(Cell::new(1)) } } const fn bar() -> NonZero> { let mut x = unsafe { NonZero(Cell::new(1)) }; - let y = unsafe { &x.0 }; //~ ERROR cannot borrow a constant which may contain interior mut + let y = unsafe { &x.0 }; //~ ERROR the borrowed element may contain interior mutability unsafe { NonZero(Cell::new(1)) } } diff --git a/src/test/ui/unsafe/ranged_ints3_const.stderr b/src/test/ui/unsafe/ranged_ints3_const.stderr index d2eb3bc5360..215005571f6 100644 --- a/src/test/ui/unsafe/ranged_ints3_const.stderr +++ b/src/test/ui/unsafe/ranged_ints3_const.stderr @@ -1,14 +1,20 @@ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability --> $DIR/ranged_ints3_const.rs:12:13 | LL | let y = &x.0; | ^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability --> $DIR/ranged_ints3_const.rs:19:22 | LL | let y = unsafe { &x.0 }; | ^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block --> $DIR/ranged_ints3_const.rs:12:13 @@ -20,5 +26,5 @@ LL | let y = &x.0; error: aborting due to 3 previous errors -Some errors have detailed explanations: E0133, E0492. +Some errors have detailed explanations: E0133, E0658. For more information about an error, try `rustc --explain E0133`. From 3a44a20ed1c3ee448c3d588e9b132ddc6cd62ab9 Mon Sep 17 00:00:00 2001 From: oli Date: Sun, 27 Dec 2020 23:59:00 +0000 Subject: [PATCH 02/13] The proper name for the rule is "enclosing scope" --- compiler/rustc_mir/src/transform/check_consts/validation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 8830575f189..c2c54c94061 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -582,7 +582,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { ); if borrowed_place_has_mut_interior { - // Locals without StorageDead follow the "trailing expression" rule, meaning + // Locals without StorageDead follow the "enclosing scope" rule, meaning // they are essentially anonymous static items themselves. if self.local_has_storage_dead(place.local) { self.check_op(ops::CellBorrowBehindRef); From 354e510f7d9e9f19b5f3ff55da83658a260bca4f Mon Sep 17 00:00:00 2001 From: oli Date: Mon, 28 Dec 2020 01:09:55 +0000 Subject: [PATCH 03/13] Fix cell checks in const fn --- compiler/rustc_mir/src/transform/check_consts/ops.rs | 7 +++++++ src/test/ui/consts/std/cell.rs | 2 ++ 2 files changed, 9 insertions(+) diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index 1ee6615f6f0..5112c572d0f 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -227,6 +227,13 @@ impl NonConstOp for CellBorrowBehindRef { #[derive(Debug)] pub struct CellBorrow; impl NonConstOp for CellBorrow { + fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { + match ccx.const_kind() { + // The borrow checker does a much better job at handling these than we do + hir::ConstContext::ConstFn => Status::Allowed, + _ => Status::Forbidden, + } + } fn importance(&self) -> DiagnosticImportance { // The problematic cases will already emit a `CellBorrowBehindRef` DiagnosticImportance::Secondary diff --git a/src/test/ui/consts/std/cell.rs b/src/test/ui/consts/std/cell.rs index ee4df6f43fa..de75d868c7f 100644 --- a/src/test/ui/consts/std/cell.rs +++ b/src/test/ui/consts/std/cell.rs @@ -36,4 +36,6 @@ unsafe impl Sync for Wrap {} static BAR_PTR: Wrap<*mut u32> = Wrap(BAR.0.get()); +const fn fst_ref(x: &(T, U)) -> &T { &x.0 } + fn main() {} From 4158e58d79af7a538944c0acffbc0718551f221a Mon Sep 17 00:00:00 2001 From: oli Date: Wed, 30 Dec 2020 16:48:07 +0000 Subject: [PATCH 04/13] Enhance some comments --- .../src/transform/check_consts/validation.rs | 2 ++ src/test/ui/consts/std/cell.rs | 15 ++++++++++----- src/test/ui/consts/std/cell.stderr | 8 ++++---- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index c2c54c94061..c2b702f265b 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -584,6 +584,8 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { if borrowed_place_has_mut_interior { // Locals without StorageDead follow the "enclosing scope" rule, meaning // they are essentially anonymous static items themselves. + // Note: This is only sound if every local that has a `StorageDead` has a + // `StorageDead` in every control flow path leading to a `return` terminator. if self.local_has_storage_dead(place.local) { self.check_op(ops::CellBorrowBehindRef); } else { diff --git a/src/test/ui/consts/std/cell.rs b/src/test/ui/consts/std/cell.rs index de75d868c7f..f1ef541319a 100644 --- a/src/test/ui/consts/std/cell.rs +++ b/src/test/ui/consts/std/cell.rs @@ -2,23 +2,28 @@ use std::cell::*; -// not ok, because this would create a silent constant with interior mutability. -// the rules could be relaxed in the future +// not ok, because this creates a dangling pointer, just like `let x = Cell::new(42).as_ptr()` would static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); //~^ ERROR encountered dangling pointer const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); //~^ ERROR encountered dangling pointer +// Ok, these are just base values and it is the `Wrap` author's job to uphold `Send` and `Sync` +// invariants, since they used `unsafe impl`. static FOO3: Wrap> = Wrap(Cell::new(42)); const FOO3_CONST: Wrap> = Wrap(Cell::new(42)); -// ok +// ok, we are referring to the memory of another static item. static FOO4: Wrap<*mut u32> = Wrap(FOO3.0.as_ptr()); + +// not ok, the use of a constant here is equivalent to an inline declaration of the value, so +// its memory will get freed before the constant is finished evaluating, thus creating a dangling +// pointer. This would happen exactly the same at runtime. const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr()); //~^ ERROR encountered dangling pointer -// not ok, because the `as_ptr` call takes a reference to a type with interior mutability -// which is not allowed in constants +// not ok, because the `as_ptr` call takes a reference to a temporary that will get freed +// before the constant is finished evaluating. const FOO2: *mut u32 = Cell::new(42).as_ptr(); //~^ ERROR encountered dangling pointer diff --git a/src/test/ui/consts/std/cell.stderr b/src/test/ui/consts/std/cell.stderr index 75cae00611a..355c326f0b6 100644 --- a/src/test/ui/consts/std/cell.stderr +++ b/src/test/ui/consts/std/cell.stderr @@ -1,23 +1,23 @@ error: encountered dangling pointer in final constant - --> $DIR/cell.rs:7:1 + --> $DIR/cell.rs:6:1 | LL | static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered dangling pointer in final constant - --> $DIR/cell.rs:9:1 + --> $DIR/cell.rs:8:1 | LL | const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered dangling pointer in final constant - --> $DIR/cell.rs:17:1 + --> $DIR/cell.rs:22:1 | LL | const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered dangling pointer in final constant - --> $DIR/cell.rs:22:1 + --> $DIR/cell.rs:27:1 | LL | const FOO2: *mut u32 = Cell::new(42).as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 3ed14033f7c087492a73c70bb11c1f7bae1b06c9 Mon Sep 17 00:00:00 2001 From: oli Date: Wed, 30 Dec 2020 17:20:38 +0000 Subject: [PATCH 05/13] Reinstate the error-code error over the feature gate error --- .../src/error_codes/E0492.md | 2 -- .../src/transform/check_consts/ops.rs | 22 ++++++++++++------- .../src/transform/check_consts/validation.rs | 2 +- src/test/ui/consts/partial_qualif.rs | 2 -- src/test/ui/consts/partial_qualif.stderr | 2 +- src/test/ui/consts/qualif_overwrite.rs | 2 -- src/test/ui/consts/qualif_overwrite.stderr | 2 +- src/test/ui/consts/qualif_overwrite_2.rs | 2 -- src/test/ui/consts/qualif_overwrite_2.stderr | 2 +- src/test/ui/error-codes/E0492.rs | 2 -- src/test/ui/error-codes/E0492.stderr | 4 ++-- .../ui/issues/issue-17718-const-borrow.rs | 2 -- .../ui/issues/issue-17718-const-borrow.stderr | 6 ++--- 13 files changed, 23 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0492.md b/compiler/rustc_error_codes/src/error_codes/E0492.md index 30235b0aeb0..79e7c069a91 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0492.md +++ b/compiler/rustc_error_codes/src/error_codes/E0492.md @@ -3,7 +3,6 @@ A borrow of a constant containing interior mutability was attempted. Erroneous code example: ```compile_fail,E0492 -#![feature(const_refs_to_cell)] use std::sync::atomic::AtomicUsize; const A: AtomicUsize = AtomicUsize::new(0); @@ -31,7 +30,6 @@ static B: &'static AtomicUsize = &A; // ok! You can also have this error while using a cell type: ```compile_fail,E0492 -#![feature(const_refs_to_cell)] use std::cell::Cell; const A: Cell = Cell::new(1); diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index 5112c572d0f..764031c0dae 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -209,11 +209,18 @@ impl NonConstOp for LiveDrop { } #[derive(Debug)] -pub struct CellBorrowBehindRef; -impl NonConstOp for CellBorrowBehindRef { +/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow never escapes to +/// the final value of the constant. +pub struct TransientCellBorrow; +impl NonConstOp for TransientCellBorrow { fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status { Status::Unstable(sym::const_refs_to_cell) } + fn importance(&self) -> DiagnosticImportance { + // The cases that cannot possibly work will already emit a `CellBorrow`, so we should + // not additionally emit a feature gate error if activating the feature gate won't work. + DiagnosticImportance::Secondary + } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, @@ -225,19 +232,18 @@ impl NonConstOp for CellBorrowBehindRef { } #[derive(Debug)] +/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow escapes to +/// the final value of the constant, and thus we cannot allow this (for now). We may allow +/// it in the future for static items. pub struct CellBorrow; impl NonConstOp for CellBorrow { fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { match ccx.const_kind() { - // The borrow checker does a much better job at handling these than we do - hir::ConstContext::ConstFn => Status::Allowed, + // The borrow checker does a much better job at handling these than we do. + hir::ConstContext::ConstFn => Status::Unstable(sym::const_refs_to_cell), _ => Status::Forbidden, } } - fn importance(&self) -> DiagnosticImportance { - // The problematic cases will already emit a `CellBorrowBehindRef` - DiagnosticImportance::Secondary - } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { struct_span_err!( ccx.tcx.sess, diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index c2b702f265b..f0ab3ff0100 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -587,7 +587,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { // Note: This is only sound if every local that has a `StorageDead` has a // `StorageDead` in every control flow path leading to a `return` terminator. if self.local_has_storage_dead(place.local) { - self.check_op(ops::CellBorrowBehindRef); + self.check_op(ops::TransientCellBorrow); } else { self.check_op(ops::CellBorrow); } diff --git a/src/test/ui/consts/partial_qualif.rs b/src/test/ui/consts/partial_qualif.rs index e069a023aa1..32c68e69f4b 100644 --- a/src/test/ui/consts/partial_qualif.rs +++ b/src/test/ui/consts/partial_qualif.rs @@ -1,5 +1,3 @@ -#![feature(const_refs_to_cell)] - use std::cell::Cell; const FOO: &(Cell, bool) = { diff --git a/src/test/ui/consts/partial_qualif.stderr b/src/test/ui/consts/partial_qualif.stderr index 58acde1b58a..221e449b6f9 100644 --- a/src/test/ui/consts/partial_qualif.stderr +++ b/src/test/ui/consts/partial_qualif.stderr @@ -1,5 +1,5 @@ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/partial_qualif.rs:8:5 + --> $DIR/partial_qualif.rs:6:5 | LL | &{a} | ^^^^ diff --git a/src/test/ui/consts/qualif_overwrite.rs b/src/test/ui/consts/qualif_overwrite.rs index 9c20d94c6dd..9b3f6786ae6 100644 --- a/src/test/ui/consts/qualif_overwrite.rs +++ b/src/test/ui/consts/qualif_overwrite.rs @@ -1,5 +1,3 @@ -#![feature(const_refs_to_cell)] - use std::cell::Cell; // this is overly conservative. The reset to `None` should clear `a` of all qualifications diff --git a/src/test/ui/consts/qualif_overwrite.stderr b/src/test/ui/consts/qualif_overwrite.stderr index a6c8c599ecc..fbaae711d7c 100644 --- a/src/test/ui/consts/qualif_overwrite.stderr +++ b/src/test/ui/consts/qualif_overwrite.stderr @@ -1,5 +1,5 @@ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/qualif_overwrite.rs:12:5 + --> $DIR/qualif_overwrite.rs:10:5 | LL | &{a} | ^^^^ diff --git a/src/test/ui/consts/qualif_overwrite_2.rs b/src/test/ui/consts/qualif_overwrite_2.rs index 5d0843710e2..fa79b5c14a7 100644 --- a/src/test/ui/consts/qualif_overwrite_2.rs +++ b/src/test/ui/consts/qualif_overwrite_2.rs @@ -1,5 +1,3 @@ -#![feature(const_refs_to_cell)] - use std::cell::Cell; // const qualification is not smart enough to know about fields and always assumes that there might diff --git a/src/test/ui/consts/qualif_overwrite_2.stderr b/src/test/ui/consts/qualif_overwrite_2.stderr index f109b4cea81..a393c4e336d 100644 --- a/src/test/ui/consts/qualif_overwrite_2.stderr +++ b/src/test/ui/consts/qualif_overwrite_2.stderr @@ -1,5 +1,5 @@ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/qualif_overwrite_2.rs:10:5 + --> $DIR/qualif_overwrite_2.rs:8:5 | LL | &{a.0} | ^^^^^^ diff --git a/src/test/ui/error-codes/E0492.rs b/src/test/ui/error-codes/E0492.rs index d8357f0c678..2c735fcc9f9 100644 --- a/src/test/ui/error-codes/E0492.rs +++ b/src/test/ui/error-codes/E0492.rs @@ -1,5 +1,3 @@ -#![feature(const_refs_to_cell)] - use std::sync::atomic::AtomicUsize; const A: AtomicUsize = AtomicUsize::new(0); diff --git a/src/test/ui/error-codes/E0492.stderr b/src/test/ui/error-codes/E0492.stderr index ffc4ff372a3..54306433b87 100644 --- a/src/test/ui/error-codes/E0492.stderr +++ b/src/test/ui/error-codes/E0492.stderr @@ -1,11 +1,11 @@ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/E0492.rs:6:33 + --> $DIR/E0492.rs:4:33 | LL | const B: &'static AtomicUsize = &A; | ^^ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/E0492.rs:7:34 + --> $DIR/E0492.rs:5:34 | LL | static C: &'static AtomicUsize = &A; | ^^ diff --git a/src/test/ui/issues/issue-17718-const-borrow.rs b/src/test/ui/issues/issue-17718-const-borrow.rs index 7bde2361f61..b11e83144ed 100644 --- a/src/test/ui/issues/issue-17718-const-borrow.rs +++ b/src/test/ui/issues/issue-17718-const-borrow.rs @@ -1,5 +1,3 @@ -#![feature(const_refs_to_cell)] - use std::cell::UnsafeCell; const A: UnsafeCell = UnsafeCell::new(1); diff --git a/src/test/ui/issues/issue-17718-const-borrow.stderr b/src/test/ui/issues/issue-17718-const-borrow.stderr index 1bfb3982bc3..b4330049689 100644 --- a/src/test/ui/issues/issue-17718-const-borrow.stderr +++ b/src/test/ui/issues/issue-17718-const-borrow.stderr @@ -1,17 +1,17 @@ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/issue-17718-const-borrow.rs:6:39 + --> $DIR/issue-17718-const-borrow.rs:4:39 | LL | const B: &'static UnsafeCell = &A; | ^^ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/issue-17718-const-borrow.rs:11:39 + --> $DIR/issue-17718-const-borrow.rs:9:39 | LL | const E: &'static UnsafeCell = &D.a; | ^^^^ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/issue-17718-const-borrow.rs:13:23 + --> $DIR/issue-17718-const-borrow.rs:11:23 | LL | const F: &'static C = &D; | ^^ From aaee3f27eec3e14e28436cdcc6ffe469d400c789 Mon Sep 17 00:00:00 2001 From: oli Date: Wed, 30 Dec 2020 17:44:11 +0000 Subject: [PATCH 06/13] Don't mix feature gates and hard errors, decide on one per op and stick with it --- .../src/transform/check_consts/ops.rs | 7 ----- .../src/transform/check_consts/validation.rs | 26 +++++++++++++------ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index 764031c0dae..cb6d16bc207 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -237,13 +237,6 @@ impl NonConstOp for TransientCellBorrow { /// it in the future for static items. pub struct CellBorrow; impl NonConstOp for CellBorrow { - fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { - match ccx.const_kind() { - // The borrow checker does a much better job at handling these than we do. - hir::ConstContext::ConstFn => Status::Unstable(sym::const_refs_to_cell), - _ => Status::Forbidden, - } - } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { struct_span_err!( ccx.tcx.sess, diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index f0ab3ff0100..4770d659032 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -582,14 +582,24 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { ); if borrowed_place_has_mut_interior { - // Locals without StorageDead follow the "enclosing scope" rule, meaning - // they are essentially anonymous static items themselves. - // Note: This is only sound if every local that has a `StorageDead` has a - // `StorageDead` in every control flow path leading to a `return` terminator. - if self.local_has_storage_dead(place.local) { - self.check_op(ops::TransientCellBorrow); - } else { - self.check_op(ops::CellBorrow); + match self.const_kind() { + // In a const fn all borrows are transient or point to the places given via + // references in the arguments. The borrow checker guarantees that. + // NOTE: Once we have heap allocations during CTFE we need to figure out + // how to prevent `const fn` to create long-lived allocations that point + // to (interior) mutable memory. + hir::ConstContext::ConstFn => self.check_op(ops::TransientCellBorrow), + _ => { + // Locals without StorageDead follow the "enclosing scope" rule, meaning + // they are essentially anonymous static items themselves. + // Note: This is only sound if every local that has a `StorageDead` has a + // `StorageDead` in every control flow path leading to a `return` terminator. + if self.local_has_storage_dead(place.local) { + self.check_op(ops::TransientCellBorrow); + } else { + self.check_op(ops::CellBorrow); + } + } } } } From ba3a876592c41e210f41101ffaade7e21b39fc2c Mon Sep 17 00:00:00 2001 From: oli Date: Fri, 1 Jan 2021 18:45:44 +0000 Subject: [PATCH 07/13] Bless ui tests --- src/test/ui/panic-handler/weak-lang-item.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/panic-handler/weak-lang-item.stderr b/src/test/ui/panic-handler/weak-lang-item.stderr index b7c040c7a85..68e3e21df3e 100644 --- a/src/test/ui/panic-handler/weak-lang-item.stderr +++ b/src/test/ui/panic-handler/weak-lang-item.stderr @@ -10,10 +10,10 @@ help: you can use `as` to change the binding name of the import LL | extern crate core as other_core; | -error: `#[panic_handler]` function required, but not found - error: language item required, but not found: `eh_personality` +error: `#[panic_handler]` function required, but not found + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0259`. From e5330a4f52fcf9de8112f3dd0abb094640b668e3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sun, 3 Jan 2021 14:20:51 +0100 Subject: [PATCH 08/13] Apply suggestions from code review comment nits Co-authored-by: Ralf Jung --- compiler/rustc_mir/src/transform/check_consts/ops.rs | 2 +- .../src/transform/check_consts/validation.rs | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index cb6d16bc207..a85303d4cd3 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -232,7 +232,7 @@ impl NonConstOp for TransientCellBorrow { } #[derive(Debug)] -/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow escapes to +/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow might escape to /// the final value of the constant, and thus we cannot allow this (for now). We may allow /// it in the future for static items. pub struct CellBorrow; diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 4770d659032..8c2525879b3 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -584,14 +584,19 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { if borrowed_place_has_mut_interior { match self.const_kind() { // In a const fn all borrows are transient or point to the places given via - // references in the arguments. The borrow checker guarantees that. + // references in the arguments (so we already checked them with + // TransientCellBorrow/CellBorrow as appropriate). + // The borrow checker guarantees that no new non-transient borrows are created. // NOTE: Once we have heap allocations during CTFE we need to figure out // how to prevent `const fn` to create long-lived allocations that point // to (interior) mutable memory. hir::ConstContext::ConstFn => self.check_op(ops::TransientCellBorrow), _ => { - // Locals without StorageDead follow the "enclosing scope" rule, meaning - // they are essentially anonymous static items themselves. + // Locals StorageDead are known to not leak to the final constant, and + // it is thus inherently safe to permit such locals to have their + // address taken as we can't end up with a reference to them in the + // final value without creating a dangling pointer, which will cause + // errors during validation. // Note: This is only sound if every local that has a `StorageDead` has a // `StorageDead` in every control flow path leading to a `return` terminator. if self.local_has_storage_dead(place.local) { From a137ff17069feb67a2ef5a0f3ddbe09707c2d6cd Mon Sep 17 00:00:00 2001 From: oli Date: Sun, 3 Jan 2021 13:45:16 +0000 Subject: [PATCH 09/13] Update now-more-precise operation with a preciser message --- compiler/rustc_mir/src/transform/check_consts/ops.rs | 4 ++-- src/test/ui/consts/partial_qualif.rs | 2 +- src/test/ui/consts/partial_qualif.stderr | 2 +- src/test/ui/consts/qualif_overwrite.rs | 2 +- src/test/ui/consts/qualif_overwrite.stderr | 2 +- src/test/ui/consts/qualif_overwrite_2.rs | 2 +- src/test/ui/consts/qualif_overwrite_2.stderr | 2 +- src/test/ui/error-codes/E0492.stderr | 4 ++-- src/test/ui/issues/issue-17718-const-borrow.rs | 6 +++--- src/test/ui/issues/issue-17718-const-borrow.stderr | 6 +++--- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index a85303d4cd3..cf81b69fede 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -242,8 +242,8 @@ impl NonConstOp for CellBorrow { ccx.tcx.sess, span, E0492, - "cannot borrow a constant which may contain \ - interior mutability, create a static instead" + "this borrow to an interior mutable value may end up in the final value of this {}", + ccx.const_kind(), ) } } diff --git a/src/test/ui/consts/partial_qualif.rs b/src/test/ui/consts/partial_qualif.rs index 32c68e69f4b..4aacdec7c51 100644 --- a/src/test/ui/consts/partial_qualif.rs +++ b/src/test/ui/consts/partial_qualif.rs @@ -3,7 +3,7 @@ use std::cell::Cell; const FOO: &(Cell, bool) = { let mut a = (Cell::new(0), false); a.1 = true; // sets `qualif(a)` to `qualif(a) | qualif(true)` - &{a} //~ ERROR cannot borrow a constant which may contain interior mutability + &{a} //~ ERROR borrow to an interior mutable value may end up in the final value }; fn main() {} diff --git a/src/test/ui/consts/partial_qualif.stderr b/src/test/ui/consts/partial_qualif.stderr index 221e449b6f9..5ea0cbc4f7c 100644 --- a/src/test/ui/consts/partial_qualif.stderr +++ b/src/test/ui/consts/partial_qualif.stderr @@ -1,4 +1,4 @@ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant --> $DIR/partial_qualif.rs:6:5 | LL | &{a} diff --git a/src/test/ui/consts/qualif_overwrite.rs b/src/test/ui/consts/qualif_overwrite.rs index 9b3f6786ae6..485a4a2fcc3 100644 --- a/src/test/ui/consts/qualif_overwrite.rs +++ b/src/test/ui/consts/qualif_overwrite.rs @@ -7,7 +7,7 @@ use std::cell::Cell; const FOO: &Option> = { let mut a = Some(Cell::new(0)); a = None; // sets `qualif(a)` to `qualif(a) | qualif(None)` - &{a}//~ ERROR cannot borrow a constant which may contain interior mutability + &{a} //~ ERROR borrow to an interior mutable value may end up in the final value }; fn main() {} diff --git a/src/test/ui/consts/qualif_overwrite.stderr b/src/test/ui/consts/qualif_overwrite.stderr index fbaae711d7c..995f8600587 100644 --- a/src/test/ui/consts/qualif_overwrite.stderr +++ b/src/test/ui/consts/qualif_overwrite.stderr @@ -1,4 +1,4 @@ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant --> $DIR/qualif_overwrite.rs:10:5 | LL | &{a} diff --git a/src/test/ui/consts/qualif_overwrite_2.rs b/src/test/ui/consts/qualif_overwrite_2.rs index fa79b5c14a7..6b90988869d 100644 --- a/src/test/ui/consts/qualif_overwrite_2.rs +++ b/src/test/ui/consts/qualif_overwrite_2.rs @@ -5,7 +5,7 @@ use std::cell::Cell; const FOO: &Option> = { let mut a = (Some(Cell::new(0)),); a.0 = None; // sets `qualif(a)` to `qualif(a) | qualif(None)` - &{a.0} //~ ERROR cannot borrow a constant which may contain interior mutability + &{a.0} //~ ERROR borrow to an interior mutable value may end up in the final value }; fn main() {} diff --git a/src/test/ui/consts/qualif_overwrite_2.stderr b/src/test/ui/consts/qualif_overwrite_2.stderr index a393c4e336d..006199514fc 100644 --- a/src/test/ui/consts/qualif_overwrite_2.stderr +++ b/src/test/ui/consts/qualif_overwrite_2.stderr @@ -1,4 +1,4 @@ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant --> $DIR/qualif_overwrite_2.rs:8:5 | LL | &{a.0} diff --git a/src/test/ui/error-codes/E0492.stderr b/src/test/ui/error-codes/E0492.stderr index 54306433b87..9aa84c2bff3 100644 --- a/src/test/ui/error-codes/E0492.stderr +++ b/src/test/ui/error-codes/E0492.stderr @@ -1,10 +1,10 @@ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant --> $DIR/E0492.rs:4:33 | LL | const B: &'static AtomicUsize = &A; | ^^ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0492]: this borrow to an interior mutable value may end up in the final value of this static --> $DIR/E0492.rs:5:34 | LL | static C: &'static AtomicUsize = &A; diff --git a/src/test/ui/issues/issue-17718-const-borrow.rs b/src/test/ui/issues/issue-17718-const-borrow.rs index b11e83144ed..4b13c0f0c15 100644 --- a/src/test/ui/issues/issue-17718-const-borrow.rs +++ b/src/test/ui/issues/issue-17718-const-borrow.rs @@ -2,13 +2,13 @@ use std::cell::UnsafeCell; const A: UnsafeCell = UnsafeCell::new(1); const B: &'static UnsafeCell = &A; -//~^ ERROR: may contain interior mutability +//~^ ERROR: borrow to an interior mutable value struct C { a: UnsafeCell } const D: C = C { a: UnsafeCell::new(1) }; const E: &'static UnsafeCell = &D.a; -//~^ ERROR: may contain interior mutability +//~^ ERROR: borrow to an interior mutable value const F: &'static C = &D; -//~^ ERROR: may contain interior mutability +//~^ ERROR: borrow to an interior mutable value fn main() {} diff --git a/src/test/ui/issues/issue-17718-const-borrow.stderr b/src/test/ui/issues/issue-17718-const-borrow.stderr index b4330049689..c94ae2a3a18 100644 --- a/src/test/ui/issues/issue-17718-const-borrow.stderr +++ b/src/test/ui/issues/issue-17718-const-borrow.stderr @@ -1,16 +1,16 @@ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant --> $DIR/issue-17718-const-borrow.rs:4:39 | LL | const B: &'static UnsafeCell = &A; | ^^ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant --> $DIR/issue-17718-const-borrow.rs:9:39 | LL | const E: &'static UnsafeCell = &D.a; | ^^^^ -error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead +error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant --> $DIR/issue-17718-const-borrow.rs:11:23 | LL | const F: &'static C = &D; From e5e4a851c493a739a18d69794f5c7f3ab943b412 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sun, 3 Jan 2021 15:15:23 +0100 Subject: [PATCH 10/13] Grammar fixes Co-authored-by: Ralf Jung --- compiler/rustc_mir/src/transform/check_consts/validation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 8c2525879b3..0e3dfb44228 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -592,7 +592,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { // to (interior) mutable memory. hir::ConstContext::ConstFn => self.check_op(ops::TransientCellBorrow), _ => { - // Locals StorageDead are known to not leak to the final constant, and + // Locals with StorageDead are definitely not part of the final constant value, and // it is thus inherently safe to permit such locals to have their // address taken as we can't end up with a reference to them in the // final value without creating a dangling pointer, which will cause From 8968c8a103cd69202e4312ad497e641a8f027e88 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sun, 3 Jan 2021 15:19:07 +0100 Subject: [PATCH 11/13] Dangling pointers point to everything and nothing Co-authored-by: Ralf Jung --- compiler/rustc_mir/src/transform/check_consts/validation.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 0e3dfb44228..d1c07d1051d 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -595,8 +595,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { // Locals with StorageDead are definitely not part of the final constant value, and // it is thus inherently safe to permit such locals to have their // address taken as we can't end up with a reference to them in the - // final value without creating a dangling pointer, which will cause - // errors during validation. + // final value. // Note: This is only sound if every local that has a `StorageDead` has a // `StorageDead` in every control flow path leading to a `return` terminator. if self.local_has_storage_dead(place.local) { From d3992f36ad344d15db8c25f1ef1f0d302e3ad3a8 Mon Sep 17 00:00:00 2001 From: oli Date: Sun, 3 Jan 2021 14:46:19 +0000 Subject: [PATCH 12/13] Refactor the non-transient cell borrow error diagnostic --- .../src/transform/check_consts/ops.rs | 25 ++++++++++++++++--- src/test/ui/consts/partial_qualif.rs | 2 +- src/test/ui/consts/partial_qualif.stderr | 4 +-- src/test/ui/consts/qualif_overwrite.rs | 2 +- src/test/ui/consts/qualif_overwrite.stderr | 4 +-- src/test/ui/consts/qualif_overwrite_2.rs | 2 +- src/test/ui/consts/qualif_overwrite_2.stderr | 4 +-- src/test/ui/error-codes/E0492.stderr | 10 +++++--- .../ui/issues/issue-17718-const-borrow.rs | 6 ++--- .../ui/issues/issue-17718-const-borrow.stderr | 12 ++++----- 10 files changed, 46 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index cf81b69fede..945b422e29c 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -238,13 +238,32 @@ impl NonConstOp for TransientCellBorrow { pub struct CellBorrow; impl NonConstOp for CellBorrow { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - struct_span_err!( + let mut err = struct_span_err!( ccx.tcx.sess, span, E0492, - "this borrow to an interior mutable value may end up in the final value of this {}", + "{}s cannot refer to interior mutable data", ccx.const_kind(), - ) + ); + err.span_label( + span, + format!("this borrow of an interior mutable value may end up in the final value"), + ); + if let hir::ConstContext::Static(_) = ccx.const_kind() { + err.help( + "To fix this, the value can be extracted to separate \ + `static` and then referenced.", + ); + } + if ccx.tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "A constant containing interior mutable data behind a reference can allow you + to modify that data. This would make multiple uses of a constant to be able to + see different values and allow one to escape the `Send` and `Sync` requirements + for shared mutable data, which is unsound.", + ); + } + err } } diff --git a/src/test/ui/consts/partial_qualif.rs b/src/test/ui/consts/partial_qualif.rs index 4aacdec7c51..7c28b8b8a62 100644 --- a/src/test/ui/consts/partial_qualif.rs +++ b/src/test/ui/consts/partial_qualif.rs @@ -3,7 +3,7 @@ use std::cell::Cell; const FOO: &(Cell, bool) = { let mut a = (Cell::new(0), false); a.1 = true; // sets `qualif(a)` to `qualif(a) | qualif(true)` - &{a} //~ ERROR borrow to an interior mutable value may end up in the final value + &{a} //~ ERROR cannot refer to interior mutable }; fn main() {} diff --git a/src/test/ui/consts/partial_qualif.stderr b/src/test/ui/consts/partial_qualif.stderr index 5ea0cbc4f7c..32c25be2173 100644 --- a/src/test/ui/consts/partial_qualif.stderr +++ b/src/test/ui/consts/partial_qualif.stderr @@ -1,8 +1,8 @@ -error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant +error[E0492]: constants cannot refer to interior mutable data --> $DIR/partial_qualif.rs:6:5 | LL | &{a} - | ^^^^ + | ^^^^ this borrow of an interior mutable value may end up in the final value error: aborting due to previous error diff --git a/src/test/ui/consts/qualif_overwrite.rs b/src/test/ui/consts/qualif_overwrite.rs index 485a4a2fcc3..aae4e41ffd7 100644 --- a/src/test/ui/consts/qualif_overwrite.rs +++ b/src/test/ui/consts/qualif_overwrite.rs @@ -7,7 +7,7 @@ use std::cell::Cell; const FOO: &Option> = { let mut a = Some(Cell::new(0)); a = None; // sets `qualif(a)` to `qualif(a) | qualif(None)` - &{a} //~ ERROR borrow to an interior mutable value may end up in the final value + &{a} //~ ERROR cannot refer to interior mutable }; fn main() {} diff --git a/src/test/ui/consts/qualif_overwrite.stderr b/src/test/ui/consts/qualif_overwrite.stderr index 995f8600587..86a669c433d 100644 --- a/src/test/ui/consts/qualif_overwrite.stderr +++ b/src/test/ui/consts/qualif_overwrite.stderr @@ -1,8 +1,8 @@ -error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant +error[E0492]: constants cannot refer to interior mutable data --> $DIR/qualif_overwrite.rs:10:5 | LL | &{a} - | ^^^^ + | ^^^^ this borrow of an interior mutable value may end up in the final value error: aborting due to previous error diff --git a/src/test/ui/consts/qualif_overwrite_2.rs b/src/test/ui/consts/qualif_overwrite_2.rs index 6b90988869d..1819d9a6d20 100644 --- a/src/test/ui/consts/qualif_overwrite_2.rs +++ b/src/test/ui/consts/qualif_overwrite_2.rs @@ -5,7 +5,7 @@ use std::cell::Cell; const FOO: &Option> = { let mut a = (Some(Cell::new(0)),); a.0 = None; // sets `qualif(a)` to `qualif(a) | qualif(None)` - &{a.0} //~ ERROR borrow to an interior mutable value may end up in the final value + &{a.0} //~ ERROR cannot refer to interior mutable }; fn main() {} diff --git a/src/test/ui/consts/qualif_overwrite_2.stderr b/src/test/ui/consts/qualif_overwrite_2.stderr index 006199514fc..9eb123d0b01 100644 --- a/src/test/ui/consts/qualif_overwrite_2.stderr +++ b/src/test/ui/consts/qualif_overwrite_2.stderr @@ -1,8 +1,8 @@ -error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant +error[E0492]: constants cannot refer to interior mutable data --> $DIR/qualif_overwrite_2.rs:8:5 | LL | &{a.0} - | ^^^^^^ + | ^^^^^^ this borrow of an interior mutable value may end up in the final value error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0492.stderr b/src/test/ui/error-codes/E0492.stderr index 9aa84c2bff3..e8041af99b5 100644 --- a/src/test/ui/error-codes/E0492.stderr +++ b/src/test/ui/error-codes/E0492.stderr @@ -1,14 +1,16 @@ -error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant +error[E0492]: constants cannot refer to interior mutable data --> $DIR/E0492.rs:4:33 | LL | const B: &'static AtomicUsize = &A; - | ^^ + | ^^ this borrow of an interior mutable value may end up in the final value -error[E0492]: this borrow to an interior mutable value may end up in the final value of this static +error[E0492]: statics cannot refer to interior mutable data --> $DIR/E0492.rs:5:34 | LL | static C: &'static AtomicUsize = &A; - | ^^ + | ^^ this borrow of an interior mutable value may end up in the final value + | + = help: To fix this, the value can be extracted to separate `static` and then referenced. error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-17718-const-borrow.rs b/src/test/ui/issues/issue-17718-const-borrow.rs index 4b13c0f0c15..89316dbd5c4 100644 --- a/src/test/ui/issues/issue-17718-const-borrow.rs +++ b/src/test/ui/issues/issue-17718-const-borrow.rs @@ -2,13 +2,13 @@ use std::cell::UnsafeCell; const A: UnsafeCell = UnsafeCell::new(1); const B: &'static UnsafeCell = &A; -//~^ ERROR: borrow to an interior mutable value +//~^ ERROR: cannot refer to interior mutable struct C { a: UnsafeCell } const D: C = C { a: UnsafeCell::new(1) }; const E: &'static UnsafeCell = &D.a; -//~^ ERROR: borrow to an interior mutable value +//~^ ERROR: cannot refer to interior mutable const F: &'static C = &D; -//~^ ERROR: borrow to an interior mutable value +//~^ ERROR: cannot refer to interior mutable fn main() {} diff --git a/src/test/ui/issues/issue-17718-const-borrow.stderr b/src/test/ui/issues/issue-17718-const-borrow.stderr index c94ae2a3a18..e3ff6c923ad 100644 --- a/src/test/ui/issues/issue-17718-const-borrow.stderr +++ b/src/test/ui/issues/issue-17718-const-borrow.stderr @@ -1,20 +1,20 @@ -error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant +error[E0492]: constants cannot refer to interior mutable data --> $DIR/issue-17718-const-borrow.rs:4:39 | LL | const B: &'static UnsafeCell = &A; - | ^^ + | ^^ this borrow of an interior mutable value may end up in the final value -error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant +error[E0492]: constants cannot refer to interior mutable data --> $DIR/issue-17718-const-borrow.rs:9:39 | LL | const E: &'static UnsafeCell = &D.a; - | ^^^^ + | ^^^^ this borrow of an interior mutable value may end up in the final value -error[E0492]: this borrow to an interior mutable value may end up in the final value of this constant +error[E0492]: constants cannot refer to interior mutable data --> $DIR/issue-17718-const-borrow.rs:11:23 | LL | const F: &'static C = &D; - | ^^ + | ^^ this borrow of an interior mutable value may end up in the final value error: aborting due to 3 previous errors From 90b56b94f6925003c1879660530f9e0ebdb94fa9 Mon Sep 17 00:00:00 2001 From: oli Date: Sun, 3 Jan 2021 15:11:34 +0000 Subject: [PATCH 13/13] Stylistic fixes to diagnostic messages --- compiler/rustc_mir/src/transform/check_consts/ops.rs | 6 +++--- src/test/ui/error-codes/E0492.stderr | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index 945b422e29c..9e90a7519cf 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -251,15 +251,15 @@ impl NonConstOp for CellBorrow { ); if let hir::ConstContext::Static(_) = ccx.const_kind() { err.help( - "To fix this, the value can be extracted to separate \ - `static` and then referenced.", + "to fix this, the value can be extracted to a separate \ + `static` item and then referenced", ); } if ccx.tcx.sess.teach(&err.get_code().unwrap()) { err.note( "A constant containing interior mutable data behind a reference can allow you to modify that data. This would make multiple uses of a constant to be able to - see different values and allow one to escape the `Send` and `Sync` requirements + see different values and allow circumventing the `Send` and `Sync` requirements for shared mutable data, which is unsound.", ); } diff --git a/src/test/ui/error-codes/E0492.stderr b/src/test/ui/error-codes/E0492.stderr index e8041af99b5..557c977e87d 100644 --- a/src/test/ui/error-codes/E0492.stderr +++ b/src/test/ui/error-codes/E0492.stderr @@ -10,7 +10,7 @@ error[E0492]: statics cannot refer to interior mutable data LL | static C: &'static AtomicUsize = &A; | ^^ this borrow of an interior mutable value may end up in the final value | - = help: To fix this, the value can be extracted to separate `static` and then referenced. + = help: to fix this, the value can be extracted to a separate `static` item and then referenced error: aborting due to 2 previous errors