Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a2a238f

Browse files
committedAug 17, 2024·
const-eval interning: accpt interior mutable pointers in final value (but keep rejecting mutable references)
1 parent 355a307 commit a2a238f

21 files changed

+178
-564
lines changed
 

‎compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
524524
// final value.
525525
// Note: This is only sound if every local that has a `StorageDead` has a
526526
// `StorageDead` in every control flow path leading to a `return` terminator.
527-
// The good news is that interning will detect if any unexpected mutable
528-
// pointer slips through.
527+
// If anything slips through, there's no safety net -- safe code can create
528+
// references to variants of `!Freeze` enums as long as that variant is `Freeze`,
529+
// so interning can't protect us here.
529530
if self.local_has_storage_dead(place.local) {
530531
self.check_op(ops::TransientCellBorrow);
531532
} else {

‎compiler/rustc_const_eval/src/const_eval/eval_queries.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,19 @@ use rustc_middle::traits::Reveal;
1010
use rustc_middle::ty::layout::LayoutOf;
1111
use rustc_middle::ty::print::with_no_trimmed_paths;
1212
use rustc_middle::ty::{self, Ty, TyCtxt};
13-
use rustc_session::lint;
1413
use rustc_span::def_id::LocalDefId;
1514
use rustc_span::{Span, DUMMY_SP};
1615
use rustc_target::abi::{self, Abi};
1716
use tracing::{debug, instrument, trace};
1817

1918
use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
2019
use crate::const_eval::CheckAlignment;
21-
use crate::errors::{self, ConstEvalError, DanglingPtrInFinal};
2220
use crate::interpret::{
2321
create_static_alloc, eval_nullary_intrinsic, intern_const_alloc_recursive, throw_exhaust,
2422
CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpError,
2523
InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup,
2624
};
27-
use crate::CTRL_C_RECEIVED;
25+
use crate::{errors, CTRL_C_RECEIVED};
2826

2927
// Returns a pointer to where the result lives
3028
#[instrument(level = "trace", skip(ecx, body))]
@@ -105,18 +103,15 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
105103
return Err(ecx
106104
.tcx
107105
.dcx()
108-
.emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind })
106+
.emit_err(errors::DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind })
109107
.into());
110108
}
111109
Err(InternResult::FoundBadMutablePointer) => {
112-
// only report mutable pointers if there were no dangling pointers
113-
let err_diag = errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind };
114-
ecx.tcx.emit_node_span_lint(
115-
lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
116-
ecx.machine.best_lint_scope(*ecx.tcx),
117-
err_diag.span,
118-
err_diag,
119-
)
110+
return Err(ecx
111+
.tcx
112+
.dcx()
113+
.emit_err(errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind })
114+
.into());
120115
}
121116
}
122117

@@ -448,7 +443,12 @@ fn report_eval_error<'tcx>(
448443
error,
449444
DUMMY_SP,
450445
|| super::get_span_and_frames(ecx.tcx, ecx.stack()),
451-
|span, frames| ConstEvalError { span, error_kind: kind, instance, frame_notes: frames },
446+
|span, frames| errors::ConstEvalError {
447+
span,
448+
error_kind: kind,
449+
instance,
450+
frame_notes: frames,
451+
},
452452
)
453453
}
454454

‎compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -712,16 +712,29 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
712712
_kind: mir::RetagKind,
713713
val: &ImmTy<'tcx, CtfeProvenance>,
714714
) -> InterpResult<'tcx, ImmTy<'tcx, CtfeProvenance>> {
715-
// If it's a frozen shared reference that's not already immutable, make it immutable.
715+
// If it's a frozen shared reference that's not already immutable, potentially make it immutable.
716716
// (Do nothing on `None` provenance, that cannot store immutability anyway.)
717717
if let ty::Ref(_, ty, mutbl) = val.layout.ty.kind()
718718
&& *mutbl == Mutability::Not
719-
&& val.to_scalar_and_meta().0.to_pointer(ecx)?.provenance.is_some_and(|p| !p.immutable())
720-
// That next check is expensive, that's why we have all the guards above.
721-
&& ty.is_freeze(*ecx.tcx, ecx.param_env)
719+
&& val
720+
.to_scalar_and_meta()
721+
.0
722+
.to_pointer(ecx)?
723+
.provenance
724+
.is_some_and(|p| !p.immutable())
722725
{
726+
// That next check is expensive, that's why we have all the guards above.
727+
let is_immutable = ty.is_freeze(*ecx.tcx, ecx.param_env);
723728
let place = ecx.ref_to_mplace(val)?;
724-
let new_place = place.map_provenance(CtfeProvenance::as_immutable);
729+
let new_place = if is_immutable {
730+
place.map_provenance(CtfeProvenance::as_immutable)
731+
} else {
732+
// Even if it is not immutable, remember that it is a shared reference.
733+
// This allows it to become part of the final value of the constant.
734+
// (See <https://github.com/rust-lang/rust/pull/128543> for why we allow this
735+
// even when there is interior mutability.)
736+
place.map_provenance(CtfeProvenance::as_shared_ref)
737+
};
725738
Ok(ImmTy::from_immediate(new_place.to_ref(ecx), val.layout))
726739
} else {
727740
Ok(val.clone())

‎compiler/rustc_const_eval/src/errors.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,10 @@ pub(crate) struct NestedStaticInThreadLocal {
3535
pub span: Span,
3636
}
3737

38-
#[derive(LintDiagnostic)]
38+
#[derive(Diagnostic)]
3939
#[diag(const_eval_mutable_ptr_in_final)]
4040
pub(crate) struct MutablePtrInFinal {
41-
// rust-lang/rust#122153: This was marked as `#[primary_span]` under
42-
// `derive(Diagnostic)`. Since we expect we may hard-error in future, we are
43-
// keeping the field (and skipping it under `derive(LintDiagnostic)`).
44-
#[skip_arg]
41+
#[primary_span]
4542
pub span: Span,
4643
pub kind: InternKind,
4744
}

‎compiler/rustc_const_eval/src/interpret/intern.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,16 +223,20 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
223223
continue;
224224
}
225225

226-
// Crucially, we check this *before* checking whether the `alloc_id`
227-
// has already been interned. The point of this check is to ensure that when
228-
// there are multiple pointers to the same allocation, they are *all* immutable.
229-
// Therefore it would be bad if we only checked the first pointer to any given
230-
// allocation.
226+
// Ensure that this is is derived from a shared reference. Crucially, we check this *before*
227+
// checking whether the `alloc_id` has already been interned. The point of this check is to
228+
// ensure that when there are multiple pointers to the same allocation, they are *all*
229+
// derived from a shared reference. Therefore it would be bad if we only checked the first
230+
// pointer to any given allocation.
231231
// (It is likely not possible to actually have multiple pointers to the same allocation,
232232
// so alternatively we could also check that and ICE if there are multiple such pointers.)
233+
// See <https://github.com/rust-lang/rust/pull/128543> for why we are checking for
234+
// "shared reference" and not "immutable", i.e., for why we are allowed interior-mutable
235+
// shared references: they can actually be created in safe code while pointing to apparently
236+
// "immutable" values, via promotion of `&None::<Cell<T>>`.
233237
if intern_kind != InternKind::Promoted
234238
&& inner_mutability == Mutability::Not
235-
&& !prov.immutable()
239+
&& !prov.shared_ref()
236240
{
237241
if ecx.tcx.try_get_global_alloc(alloc_id).is_some()
238242
&& !just_interned.contains(&alloc_id)
@@ -245,7 +249,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
245249
// this to the todo list, since after all it is already interned.
246250
continue;
247251
}
248-
// Found a mutable pointer inside a const where inner allocations should be
252+
// Found a mutable reference inside a const where inner allocations should be
249253
// immutable. We exclude promoteds from this, since things like `&mut []` and
250254
// `&None::<Cell<i32>>` lead to promotion that can produce mutable pointers. We rely
251255
// on the promotion analysis not screwing up to ensure that it is sound to intern

‎compiler/rustc_lint/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,11 @@ fn register_builtins(store: &mut LintStore) {
569569
"byte_slice_in_packed_struct_with_derive",
570570
"converted into hard error, see issue #107457 \
571571
<https://github.com/rust-lang/rust/issues/107457> for more information",
572-
)
572+
);
573+
store.register_removed(
574+
"const_eval_mutable_ptr_in_final_value",
575+
"partially allowed now, otherwise turned into a hard error",
576+
);
573577
}
574578

575579
fn register_internals(store: &mut LintStore) {

‎compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ declare_lint_pass! {
2929
CENUM_IMPL_DROP_CAST,
3030
COHERENCE_LEAK_CHECK,
3131
CONFLICTING_REPR_HINTS,
32-
CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
3332
CONST_EVALUATABLE_UNCHECKED,
3433
CONST_ITEM_MUTATION,
3534
DEAD_CODE,
@@ -2772,51 +2771,6 @@ declare_lint! {
27722771
@feature_gate = strict_provenance;
27732772
}
27742773

2775-
declare_lint! {
2776-
/// The `const_eval_mutable_ptr_in_final_value` lint detects if a mutable pointer
2777-
/// has leaked into the final value of a const expression.
2778-
///
2779-
/// ### Example
2780-
///
2781-
/// ```rust
2782-
/// pub enum JsValue {
2783-
/// Undefined,
2784-
/// Object(std::cell::Cell<bool>),
2785-
/// }
2786-
///
2787-
/// impl ::std::ops::Drop for JsValue {
2788-
/// fn drop(&mut self) {}
2789-
/// }
2790-
///
2791-
/// const UNDEFINED: &JsValue = &JsValue::Undefined;
2792-
///
2793-
/// fn main() {
2794-
/// }
2795-
/// ```
2796-
///
2797-
/// {{produces}}
2798-
///
2799-
/// ### Explanation
2800-
///
2801-
/// In the 1.77 release, the const evaluation machinery adopted some
2802-
/// stricter rules to reject expressions with values that could
2803-
/// end up holding mutable references to state stored in static memory
2804-
/// (which is inherently immutable).
2805-
///
2806-
/// This is a [future-incompatible] lint to ease the transition to an error.
2807-
/// See [issue #122153] for more details.
2808-
///
2809-
/// [issue #122153]: https://github.com/rust-lang/rust/issues/122153
2810-
/// [future-incompatible]: ../index.md#future-incompatible-lints
2811-
pub CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
2812-
Warn,
2813-
"detects a mutable pointer that has leaked into final value of a const expression",
2814-
@future_incompatible = FutureIncompatibleInfo {
2815-
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
2816-
reference: "issue #122153 <https://github.com/rust-lang/rust/issues/122153>",
2817-
};
2818-
}
2819-
28202774
declare_lint! {
28212775
/// The `const_evaluatable_unchecked` lint detects a generic constant used
28222776
/// in a type.

‎compiler/rustc_middle/src/mir/interpret/pointer.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,23 @@ pub trait Provenance: Copy + fmt::Debug + 'static {
8080
}
8181

8282
/// The type of provenance in the compile-time interpreter.
83-
/// This is a packed representation of an `AllocId` and an `immutable: bool`.
83+
/// This is a packed representation of:
84+
/// - an `AllocId` (non-zero)
85+
/// - an `immutable: bool`
86+
/// - a `shared_ref: bool`
87+
///
88+
/// with the extra invariant that if `immutable` is `true`, then so
89+
/// is `shared_ref`.
8490
#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
8591
pub struct CtfeProvenance(NonZero<u64>);
8692

8793
impl From<AllocId> for CtfeProvenance {
8894
fn from(value: AllocId) -> Self {
8995
let prov = CtfeProvenance(value.0);
90-
assert!(!prov.immutable(), "`AllocId` with the highest bit set cannot be used in CTFE");
96+
assert!(
97+
prov.alloc_id() == value,
98+
"`AllocId` with the highest bits set cannot be used in CTFE"
99+
);
91100
prov
92101
}
93102
}
@@ -103,12 +112,14 @@ impl fmt::Debug for CtfeProvenance {
103112
}
104113

105114
const IMMUTABLE_MASK: u64 = 1 << 63; // the highest bit
115+
const SHARED_REF_MASK: u64 = 1 << 62;
116+
const ALLOC_ID_MASK: u64 = u64::MAX & !IMMUTABLE_MASK & !SHARED_REF_MASK;
106117

107118
impl CtfeProvenance {
108119
/// Returns the `AllocId` of this provenance.
109120
#[inline(always)]
110121
pub fn alloc_id(self) -> AllocId {
111-
AllocId(NonZero::new(self.0.get() & !IMMUTABLE_MASK).unwrap())
122+
AllocId(NonZero::new(self.0.get() & ALLOC_ID_MASK).unwrap())
112123
}
113124

114125
/// Returns whether this provenance is immutable.
@@ -117,10 +128,38 @@ impl CtfeProvenance {
117128
self.0.get() & IMMUTABLE_MASK != 0
118129
}
119130

131+
/// Returns whether this provenance is derived from a shared reference.
132+
#[inline]
133+
pub fn shared_ref(self) -> bool {
134+
self.0.get() & SHARED_REF_MASK != 0
135+
}
136+
137+
pub fn into_parts(self) -> (AllocId, bool, bool) {
138+
(self.alloc_id(), self.immutable(), self.shared_ref())
139+
}
140+
141+
pub fn from_parts((alloc_id, immutable, shared_ref): (AllocId, bool, bool)) -> Self {
142+
let prov = CtfeProvenance::from(alloc_id);
143+
if immutable {
144+
// This sets both flas, so we don't even have to check `shared_ref`.
145+
prov.as_immutable()
146+
} else if shared_ref {
147+
prov.as_shared_ref()
148+
} else {
149+
prov
150+
}
151+
}
152+
120153
/// Returns an immutable version of this provenance.
121154
#[inline]
122155
pub fn as_immutable(self) -> Self {
123-
CtfeProvenance(self.0 | IMMUTABLE_MASK)
156+
CtfeProvenance(self.0 | IMMUTABLE_MASK | SHARED_REF_MASK)
157+
}
158+
159+
/// Returns a "shared reference" (but not necessarily immutable!) version of this provenance.
160+
#[inline]
161+
pub fn as_shared_ref(self) -> Self {
162+
CtfeProvenance(self.0 | SHARED_REF_MASK)
124163
}
125164
}
126165

‎compiler/rustc_middle/src/ty/codec.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,7 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AllocId {
165165

166166
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for CtfeProvenance {
167167
fn encode(&self, e: &mut E) {
168-
self.alloc_id().encode(e);
169-
self.immutable().encode(e);
168+
self.into_parts().encode(e);
170169
}
171170
}
172171

@@ -295,10 +294,8 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AllocId {
295294

296295
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for CtfeProvenance {
297296
fn decode(decoder: &mut D) -> Self {
298-
let alloc_id: AllocId = Decodable::decode(decoder);
299-
let prov = CtfeProvenance::from(alloc_id);
300-
let immutable: bool = Decodable::decode(decoder);
301-
if immutable { prov.as_immutable() } else { prov }
297+
let parts = Decodable::decode(decoder);
298+
CtfeProvenance::from_parts(parts)
302299
}
303300
}
304301

‎compiler/rustc_middle/src/ty/impls_ty.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,9 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
7575
}
7676
}
7777

78-
// CtfeProvenance is an AllocId and a bool.
7978
impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::CtfeProvenance {
8079
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
81-
self.alloc_id().hash_stable(hcx, hasher);
82-
self.immutable().hash_stable(hcx, hasher);
80+
self.into_parts().hash_stable(hcx, hasher);
8381
}
8482
}
8583

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
#![feature(core_intrinsics)]
22
#![feature(const_heap)]
33
#![feature(const_mut_refs)]
4-
#![deny(const_eval_mutable_ptr_in_final_value)]
54
use std::intrinsics;
65

76
const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 };
87
//~^ error: mutable pointer in final value of constant
9-
//~| WARNING this was previously accepted by the compiler
108

119
fn main() {}
Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,8 @@
11
error: encountered mutable pointer in final value of constant
2-
--> $DIR/alloc_intrinsic_untyped.rs:7:1
2+
--> $DIR/alloc_intrinsic_untyped.rs:6:1
33
|
44
LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 };
55
| ^^^^^^^^^^^^^^^^^^^
6-
|
7-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
9-
note: the lint level is defined here
10-
--> $DIR/alloc_intrinsic_untyped.rs:4:9
11-
|
12-
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
146

157
error: aborting due to 1 previous error
168

17-
Future incompatibility report: Future breakage diagnostic:
18-
error: encountered mutable pointer in final value of constant
19-
--> $DIR/alloc_intrinsic_untyped.rs:7:1
20-
|
21-
LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 };
22-
| ^^^^^^^^^^^^^^^^^^^
23-
|
24-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
25-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
26-
note: the lint level is defined here
27-
--> $DIR/alloc_intrinsic_untyped.rs:4:9
28-
|
29-
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
30-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31-

‎tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs

Lines changed: 0 additions & 18 deletions
This file was deleted.

‎tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr

Lines changed: 0 additions & 23 deletions
This file was deleted.

‎tests/ui/consts/miri_unleashed/mutable_references.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//@ normalize-stderr-test: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
44

55
#![allow(static_mut_refs)]
6-
#![deny(const_eval_mutable_ptr_in_final_value)]
76
use std::cell::UnsafeCell;
87
use std::sync::atomic::*;
98

@@ -18,13 +17,11 @@ static OH_YES: &mut i32 = &mut 42;
1817
//~| pointing to read-only memory
1918
static BAR: &mut () = &mut ();
2019
//~^ ERROR encountered mutable pointer in final value of static
21-
//~| WARNING this was previously accepted by the compiler
2220

2321
struct Foo<T>(T);
2422

2523
static BOO: &mut Foo<()> = &mut Foo(());
2624
//~^ ERROR encountered mutable pointer in final value of static
27-
//~| WARNING this was previously accepted by the compiler
2825

2926
const BLUNT: &mut i32 = &mut 42;
3027
//~^ ERROR: it is undefined behavior to use this value
@@ -81,36 +78,32 @@ const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
8178

8279
const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _;
8380
//~^ ERROR: mutable pointer in final value
84-
//~| WARNING this was previously accepted by the compiler
8581

8682
const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _;
8783
//~^ ERROR: mutable pointer in final value
88-
//~| WARNING this was previously accepted by the compiler
8984

85+
// This does *not* error since it uses a shared reference, and we have to ignore
86+
// those. See <https://github.com/rust-lang/rust/pull/128543>.
9087
const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
91-
//~^ ERROR: mutable pointer in final value
92-
//~| WARNING this was previously accepted by the compiler
9388

9489
struct SyncPtr<T> {
9590
x: *const T,
9691
}
9792
unsafe impl<T> Sync for SyncPtr<T> {}
9893

99-
// These pass the lifetime checks because of the "tail expression" / "outer scope" rule.
100-
// (This relies on `SyncPtr` being a curly brace struct.)
101-
// However, we intern the inner memory as read-only, so this must be rejected.
94+
// These pass the lifetime checks because of the "tail expression" / "outer scope" rule. (This
95+
// relies on `SyncPtr` being a curly brace struct.) However, we intern the inner memory as
96+
// read-only, so ideally this should be rejected. Unfortunately, as explained in
97+
// <https://github.com/rust-lang/rust/pull/128543>, we have to accept it.
10298
// (Also see `static-no-inner-mut` for similar tests on `static`.)
10399
const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
104-
//~^ ERROR mutable pointer in final value
105-
//~| WARNING this was previously accepted by the compiler
106100

101+
// With mutable references at least, we can detect this and error.
107102
const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ };
108103
//~^ ERROR mutable pointer in final value
109-
//~| WARNING this was previously accepted by the compiler
110104

111105
const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
112106
//~^ ERROR mutable pointer in final value
113-
//~| WARNING this was previously accepted by the compiler
114107

115108

116109
fn main() {

‎tests/ui/consts/miri_unleashed/mutable_references.stderr

Lines changed: 38 additions & 199 deletions
Large diffs are not rendered by default.
Lines changed: 13 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0080]: it is undefined behavior to use this value
2-
--> $DIR/static-no-inner-mut.rs:9:1
2+
--> $DIR/static-no-inner-mut.rs:8:1
33
|
44
LL | static REF: &AtomicI32 = &AtomicI32::new(42);
55
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory
@@ -10,7 +10,7 @@ LL | static REF: &AtomicI32 = &AtomicI32::new(42);
1010
}
1111

1212
error[E0080]: it is undefined behavior to use this value
13-
--> $DIR/static-no-inner-mut.rs:12:1
13+
--> $DIR/static-no-inner-mut.rs:11:1
1414
|
1515
LL | static REFMUT: &mut i32 = &mut 0;
1616
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
@@ -21,7 +21,7 @@ LL | static REFMUT: &mut i32 = &mut 0;
2121
}
2222

2323
error[E0080]: it is undefined behavior to use this value
24-
--> $DIR/static-no-inner-mut.rs:16:1
24+
--> $DIR/static-no-inner-mut.rs:15:1
2525
|
2626
LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
2727
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory
@@ -32,7 +32,7 @@ LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
3232
}
3333

3434
error[E0080]: it is undefined behavior to use this value
35-
--> $DIR/static-no-inner-mut.rs:18:1
35+
--> $DIR/static-no-inner-mut.rs:17:1
3636
|
3737
LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
@@ -45,118 +45,53 @@ LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
4545
error: encountered mutable pointer in final value of static
4646
--> $DIR/static-no-inner-mut.rs:34:1
4747
|
48-
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
49-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
50-
|
51-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
52-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
53-
note: the lint level is defined here
54-
--> $DIR/static-no-inner-mut.rs:6:9
55-
|
56-
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
57-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
58-
59-
error: encountered mutable pointer in final value of static
60-
--> $DIR/static-no-inner-mut.rs:38:1
61-
|
6248
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
6349
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
64-
|
65-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
66-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
6750

6851
error: encountered mutable pointer in final value of static
69-
--> $DIR/static-no-inner-mut.rs:42:1
52+
--> $DIR/static-no-inner-mut.rs:37:1
7053
|
7154
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
7255
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
73-
|
74-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
75-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
7656

7757
warning: skipping const checks
7858
|
7959
help: skipping check that does not even have a feature gate
80-
--> $DIR/static-no-inner-mut.rs:9:26
60+
--> $DIR/static-no-inner-mut.rs:8:26
8161
|
8262
LL | static REF: &AtomicI32 = &AtomicI32::new(42);
8363
| ^^^^^^^^^^^^^^^^^^^
8464
help: skipping check that does not even have a feature gate
85-
--> $DIR/static-no-inner-mut.rs:12:27
65+
--> $DIR/static-no-inner-mut.rs:11:27
8666
|
8767
LL | static REFMUT: &mut i32 = &mut 0;
8868
| ^^^^^^
8969
help: skipping check that does not even have a feature gate
90-
--> $DIR/static-no-inner-mut.rs:16:56
70+
--> $DIR/static-no-inner-mut.rs:15:56
9171
|
9272
LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
9373
| ^^^^
9474
help: skipping check that does not even have a feature gate
95-
--> $DIR/static-no-inner-mut.rs:18:44
75+
--> $DIR/static-no-inner-mut.rs:17:44
9676
|
9777
LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
9878
| ^^^^^^^^
9979
help: skipping check that does not even have a feature gate
100-
--> $DIR/static-no-inner-mut.rs:34:52
80+
--> $DIR/static-no-inner-mut.rs:31:52
10181
|
10282
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
10383
| ^^^^^^^^^^^^^^^^^^^
10484
help: skipping check that does not even have a feature gate
105-
--> $DIR/static-no-inner-mut.rs:38:51
85+
--> $DIR/static-no-inner-mut.rs:34:51
10686
|
10787
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
10888
| ^^^^^^^
10989
help: skipping check that does not even have a feature gate
110-
--> $DIR/static-no-inner-mut.rs:42:52
90+
--> $DIR/static-no-inner-mut.rs:37:52
11191
|
11292
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
11393
| ^^^^^^
11494

115-
error: aborting due to 7 previous errors; 1 warning emitted
95+
error: aborting due to 6 previous errors; 1 warning emitted
11696

11797
For more information about this error, try `rustc --explain E0080`.
118-
Future incompatibility report: Future breakage diagnostic:
119-
error: encountered mutable pointer in final value of static
120-
--> $DIR/static-no-inner-mut.rs:34:1
121-
|
122-
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
123-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
124-
|
125-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
126-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
127-
note: the lint level is defined here
128-
--> $DIR/static-no-inner-mut.rs:6:9
129-
|
130-
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
131-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
132-
133-
Future breakage diagnostic:
134-
error: encountered mutable pointer in final value of static
135-
--> $DIR/static-no-inner-mut.rs:38:1
136-
|
137-
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
138-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
139-
|
140-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
141-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
142-
note: the lint level is defined here
143-
--> $DIR/static-no-inner-mut.rs:6:9
144-
|
145-
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
146-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
147-
148-
Future breakage diagnostic:
149-
error: encountered mutable pointer in final value of static
150-
--> $DIR/static-no-inner-mut.rs:42:1
151-
|
152-
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
153-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
154-
|
155-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
156-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
157-
note: the lint level is defined here
158-
--> $DIR/static-no-inner-mut.rs:6:9
159-
|
160-
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
161-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
162-
Lines changed: 13 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0080]: it is undefined behavior to use this value
2-
--> $DIR/static-no-inner-mut.rs:9:1
2+
--> $DIR/static-no-inner-mut.rs:8:1
33
|
44
LL | static REF: &AtomicI32 = &AtomicI32::new(42);
55
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory
@@ -10,7 +10,7 @@ LL | static REF: &AtomicI32 = &AtomicI32::new(42);
1010
}
1111

1212
error[E0080]: it is undefined behavior to use this value
13-
--> $DIR/static-no-inner-mut.rs:12:1
13+
--> $DIR/static-no-inner-mut.rs:11:1
1414
|
1515
LL | static REFMUT: &mut i32 = &mut 0;
1616
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
@@ -21,7 +21,7 @@ LL | static REFMUT: &mut i32 = &mut 0;
2121
}
2222

2323
error[E0080]: it is undefined behavior to use this value
24-
--> $DIR/static-no-inner-mut.rs:16:1
24+
--> $DIR/static-no-inner-mut.rs:15:1
2525
|
2626
LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
2727
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory
@@ -32,7 +32,7 @@ LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
3232
}
3333

3434
error[E0080]: it is undefined behavior to use this value
35-
--> $DIR/static-no-inner-mut.rs:18:1
35+
--> $DIR/static-no-inner-mut.rs:17:1
3636
|
3737
LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
@@ -45,118 +45,53 @@ LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
4545
error: encountered mutable pointer in final value of static
4646
--> $DIR/static-no-inner-mut.rs:34:1
4747
|
48-
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
49-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
50-
|
51-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
52-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
53-
note: the lint level is defined here
54-
--> $DIR/static-no-inner-mut.rs:6:9
55-
|
56-
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
57-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
58-
59-
error: encountered mutable pointer in final value of static
60-
--> $DIR/static-no-inner-mut.rs:38:1
61-
|
6248
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
6349
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
64-
|
65-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
66-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
6750

6851
error: encountered mutable pointer in final value of static
69-
--> $DIR/static-no-inner-mut.rs:42:1
52+
--> $DIR/static-no-inner-mut.rs:37:1
7053
|
7154
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
7255
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
73-
|
74-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
75-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
7656

7757
warning: skipping const checks
7858
|
7959
help: skipping check that does not even have a feature gate
80-
--> $DIR/static-no-inner-mut.rs:9:26
60+
--> $DIR/static-no-inner-mut.rs:8:26
8161
|
8262
LL | static REF: &AtomicI32 = &AtomicI32::new(42);
8363
| ^^^^^^^^^^^^^^^^^^^
8464
help: skipping check that does not even have a feature gate
85-
--> $DIR/static-no-inner-mut.rs:12:27
65+
--> $DIR/static-no-inner-mut.rs:11:27
8666
|
8767
LL | static REFMUT: &mut i32 = &mut 0;
8868
| ^^^^^^
8969
help: skipping check that does not even have a feature gate
90-
--> $DIR/static-no-inner-mut.rs:16:56
70+
--> $DIR/static-no-inner-mut.rs:15:56
9171
|
9272
LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
9373
| ^^^^
9474
help: skipping check that does not even have a feature gate
95-
--> $DIR/static-no-inner-mut.rs:18:44
75+
--> $DIR/static-no-inner-mut.rs:17:44
9676
|
9777
LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
9878
| ^^^^^^^^
9979
help: skipping check that does not even have a feature gate
100-
--> $DIR/static-no-inner-mut.rs:34:52
80+
--> $DIR/static-no-inner-mut.rs:31:52
10181
|
10282
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
10383
| ^^^^^^^^^^^^^^^^^^^
10484
help: skipping check that does not even have a feature gate
105-
--> $DIR/static-no-inner-mut.rs:38:51
85+
--> $DIR/static-no-inner-mut.rs:34:51
10686
|
10787
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
10888
| ^^^^^^^
10989
help: skipping check that does not even have a feature gate
110-
--> $DIR/static-no-inner-mut.rs:42:52
90+
--> $DIR/static-no-inner-mut.rs:37:52
11191
|
11292
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
11393
| ^^^^^^
11494

115-
error: aborting due to 7 previous errors; 1 warning emitted
95+
error: aborting due to 6 previous errors; 1 warning emitted
11696

11797
For more information about this error, try `rustc --explain E0080`.
118-
Future incompatibility report: Future breakage diagnostic:
119-
error: encountered mutable pointer in final value of static
120-
--> $DIR/static-no-inner-mut.rs:34:1
121-
|
122-
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
123-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
124-
|
125-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
126-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
127-
note: the lint level is defined here
128-
--> $DIR/static-no-inner-mut.rs:6:9
129-
|
130-
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
131-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
132-
133-
Future breakage diagnostic:
134-
error: encountered mutable pointer in final value of static
135-
--> $DIR/static-no-inner-mut.rs:38:1
136-
|
137-
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
138-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
139-
|
140-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
141-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
142-
note: the lint level is defined here
143-
--> $DIR/static-no-inner-mut.rs:6:9
144-
|
145-
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
146-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
147-
148-
Future breakage diagnostic:
149-
error: encountered mutable pointer in final value of static
150-
--> $DIR/static-no-inner-mut.rs:42:1
151-
|
152-
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
153-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
154-
|
155-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
156-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
157-
note: the lint level is defined here
158-
--> $DIR/static-no-inner-mut.rs:6:9
159-
|
160-
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
161-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
162-

‎tests/ui/consts/miri_unleashed/static-no-inner-mut.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#![feature(const_refs_to_cell, const_mut_refs)]
44
// All "inner" allocations that come with a `static` are interned immutably. This means it is
55
// crucial that we do not accept any form of (interior) mutability there.
6-
#![deny(const_eval_mutable_ptr_in_final_value)]
76
use std::sync::atomic::*;
87

98
static REF: &AtomicI32 = &AtomicI32::new(42);
@@ -27,20 +26,15 @@ unsafe impl<T> Sync for SyncPtr<T> {}
2726

2827
// All of these pass the lifetime checks because of the "tail expression" / "outer scope" rule.
2928
// (This relies on `SyncPtr` being a curly brace struct.)
30-
// Then they get interned immutably, which is not great.
31-
// `mut_ref_in_final.rs` and `std/cell.rs` ensure that we don't accept this even with the feature
32-
// fate, but for unleashed Miri there's not really any way we can reject them: it's just
33-
// non-dangling raw pointers.
29+
// Then they get interned immutably, which is not great. See
30+
// <https://github.com/rust-lang/rust/pull/128543> for why we accept such code.
3431
static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
35-
//~^ ERROR mutable pointer in final value
36-
//~| WARNING this was previously accepted by the compiler
3732

33+
// With mutable references at least, we can detect this and error.
3834
static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
3935
//~^ ERROR mutable pointer in final value
40-
//~| WARNING this was previously accepted by the compiler
4136

4237
static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
4338
//~^ ERROR mutable pointer in final value
44-
//~| WARNING this was previously accepted by the compiler
4539

4640
fn main() {}

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
1818
// This one does not get promoted because of `Drop`, and then enters interesting codepaths because
1919
// as a value it has no interior mutability, but as a type it does. See
2020
// <https://github.com/rust-lang/rust/issues/121610>. Value-based reasoning for interior mutability
21-
// is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) so for now we
22-
// reject this, though not with a great error message.
21+
// is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) but we've
22+
// done it since Rust 1.0 so we can't stop now.
2323
pub enum JsValue {
2424
Undefined,
2525
Object(Cell<bool>),
@@ -28,10 +28,8 @@ impl Drop for JsValue {
2828
fn drop(&mut self) {}
2929
}
3030
const UNDEFINED: &JsValue = &JsValue::Undefined;
31-
//~^ WARNING: mutable pointer in final value of constant
32-
//~| WARNING: this was previously accepted by the compiler but is being phased out
3331

34-
// In contrast, this one works since it is being promoted.
32+
// Here's a variant of the above that uses promotion instead of the "outer scope rule" rule.
3533
const NONE: &'static Option<Cell<i32>> = &None;
3634
// Making it clear that this is promotion, not "outer scope".
3735
const NONE_EXPLICIT_PROMOTED: &'static Option<Cell<i32>> = {

‎tests/ui/consts/refs-to-cell-in-final.stderr

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,6 @@ error[E0492]: constants cannot refer to interior mutable data
1212
LL | const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
1313
| ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value
1414

15-
warning: encountered mutable pointer in final value of constant
16-
--> $DIR/refs-to-cell-in-final.rs:30:1
17-
|
18-
LL | const UNDEFINED: &JsValue = &JsValue::Undefined;
19-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
20-
|
21-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
22-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
23-
= note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default
24-
25-
error: aborting due to 2 previous errors; 1 warning emitted
15+
error: aborting due to 2 previous errors
2616

2717
For more information about this error, try `rustc --explain E0492`.
28-
Future incompatibility report: Future breakage diagnostic:
29-
warning: encountered mutable pointer in final value of constant
30-
--> $DIR/refs-to-cell-in-final.rs:30:1
31-
|
32-
LL | const UNDEFINED: &JsValue = &JsValue::Undefined;
33-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
34-
|
35-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
36-
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
37-
= note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default
38-

0 commit comments

Comments
 (0)
Please sign in to comment.