Auto merge of #128543 - RalfJung:const-interior-mut, r=fee1-dead

const-eval interning: accept interior mutable pointers in final value

…but keep rejecting mutable references

This fixes https://github.com/rust-lang/rust/issues/121610 by no longer firing the lint when there is a pointer with interior mutability in the final value of the constant. On stable, such pointers can be created with code like:
```rust
pub enum JsValue {
    Undefined,
    Object(Cell<bool>),
}
impl Drop for JsValue {
    fn drop(&mut self) {}
}
// This does *not* get promoted since `JsValue` has a destructor.
// However, the outer scope rule applies, still giving this 'static lifetime.
const UNDEFINED: &JsValue = &JsValue::Undefined;
```
It's not great to accept such values since people *might* think that it is legal to mutate them with unsafe code. (This is related to how "infectious" `UnsafeCell` is, which is a [wide open question](https://github.com/rust-lang/unsafe-code-guidelines/issues/236).) However, we [explicitly document](https://doc.rust-lang.org/reference/behavior-considered-undefined.html) that things created by `const` are immutable. Furthermore, we also accept the following even more questionable code without any lint today:
```rust
let x: &'static Option<Cell<i32>> = &None;
```
This is even more questionable since it does *not* involve a `const`, and yet still puts the data into immutable memory. We could view this as promotion [potentially introducing UB](https://github.com/rust-lang/unsafe-code-guidelines/issues/493). However, we've accepted this since ~forever and it's [too late to reject this now](https://github.com/rust-lang/rust/pull/122789); the pattern is just too useful.

So basically, if you think that `UnsafeCell` should be tracked fully precisely, then you should want the lint we currently emit to be removed, which this PR does. If you think `UnsafeCell` should "infect" surrounding `enum`s, the big problem is really https://github.com/rust-lang/unsafe-code-guidelines/issues/493 which does not trigger the lint -- the cases the lint triggers on are actually the "harmless" ones as there is an explicit surrounding `const` explaining why things end up being immutable.

What all this goes to show is that the hard error added in https://github.com/rust-lang/rust/pull/118324 (later turned into the future-compat lint that I am now suggesting we remove) was based on some wrong assumptions, at least insofar as it concerns shared references. Furthermore, that lint does not help at all for the most problematic case here where the potential UB is completely implicit. (In fact, the lint is actively in the way of [my preferred long-term strategy](https://github.com/rust-lang/unsafe-code-guidelines/issues/493#issuecomment-2028674105) for dealing with this UB.) So I think we should go back to square one and remove that error/lint for shared references. For mutable references, it does seem to work as intended, so we can keep it. Here it serves as a safety net in case the static checks that try to contain mutable references to the inside of a const initializer are not working as intended; I therefore made the check ICE to encourage users to tell us if that safety net is triggered.

Closes https://github.com/rust-lang/rust/issues/122153 by removing the lint.

Cc `@rust-lang/opsem` `@rust-lang/lang`
This commit is contained in:
bors 2024-09-14 21:11:04 +00:00
commit 9b72238eb8
23 changed files with 225 additions and 578 deletions

View File

@ -538,8 +538,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// final value. // final value.
// Note: This is only sound if every local that has a `StorageDead` has a // 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. // `StorageDead` in every control flow path leading to a `return` terminator.
// The good news is that interning will detect if any unexpected mutable // If anything slips through, there's no safety net -- safe code can create
// pointer slips through. // references to variants of `!Freeze` enums as long as that variant is `Freeze`,
// so interning can't protect us here.
if self.local_is_transient(place.local) { if self.local_is_transient(place.local) {
self.check_op(ops::TransientCellBorrow); self.check_op(ops::TransientCellBorrow);
} else { } else {

View File

@ -10,7 +10,6 @@ use rustc_middle::traits::Reveal;
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{self, Abi}; use rustc_target::abi::{self, Abi};
@ -18,13 +17,12 @@ use tracing::{debug, instrument, trace};
use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine}; use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
use crate::const_eval::CheckAlignment; use crate::const_eval::CheckAlignment;
use crate::errors::{self, ConstEvalError, DanglingPtrInFinal};
use crate::interpret::{ use crate::interpret::{
create_static_alloc, eval_nullary_intrinsic, intern_const_alloc_recursive, throw_exhaust, create_static_alloc, eval_nullary_intrinsic, intern_const_alloc_recursive, throw_exhaust,
CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpError, CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpError,
InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup,
}; };
use crate::CTRL_C_RECEIVED; use crate::{errors, CTRL_C_RECEIVED};
// Returns a pointer to where the result lives // Returns a pointer to where the result lives
#[instrument(level = "trace", skip(ecx, body))] #[instrument(level = "trace", skip(ecx, body))]
@ -100,18 +98,15 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
return Err(ecx return Err(ecx
.tcx .tcx
.dcx() .dcx()
.emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }) .emit_err(errors::DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind })
.into()); .into());
} }
Err(InternResult::FoundBadMutablePointer) => { Err(InternResult::FoundBadMutablePointer) => {
// only report mutable pointers if there were no dangling pointers return Err(ecx
let err_diag = errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }; .tcx
ecx.tcx.emit_node_span_lint( .dcx()
lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, .emit_err(errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind })
ecx.machine.best_lint_scope(*ecx.tcx), .into());
err_diag.span,
err_diag,
)
} }
} }
@ -443,7 +438,12 @@ fn report_eval_error<'tcx>(
error, error,
DUMMY_SP, DUMMY_SP,
|| super::get_span_and_frames(ecx.tcx, ecx.stack()), || super::get_span_and_frames(ecx.tcx, ecx.stack()),
|span, frames| ConstEvalError { span, error_kind: kind, instance, frame_notes: frames }, |span, frames| errors::ConstEvalError {
span,
error_kind: kind,
instance,
frame_notes: frames,
},
) )
} }

View File

@ -718,16 +718,29 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
_kind: mir::RetagKind, _kind: mir::RetagKind,
val: &ImmTy<'tcx, CtfeProvenance>, val: &ImmTy<'tcx, CtfeProvenance>,
) -> InterpResult<'tcx, ImmTy<'tcx, CtfeProvenance>> { ) -> InterpResult<'tcx, ImmTy<'tcx, CtfeProvenance>> {
// If it's a frozen shared reference that's not already immutable, make it immutable. // If it's a frozen shared reference that's not already immutable, potentially make it immutable.
// (Do nothing on `None` provenance, that cannot store immutability anyway.) // (Do nothing on `None` provenance, that cannot store immutability anyway.)
if let ty::Ref(_, ty, mutbl) = val.layout.ty.kind() if let ty::Ref(_, ty, mutbl) = val.layout.ty.kind()
&& *mutbl == Mutability::Not && *mutbl == Mutability::Not
&& val.to_scalar_and_meta().0.to_pointer(ecx)?.provenance.is_some_and(|p| !p.immutable()) && val
// That next check is expensive, that's why we have all the guards above. .to_scalar_and_meta()
&& ty.is_freeze(*ecx.tcx, ecx.param_env) .0
.to_pointer(ecx)?
.provenance
.is_some_and(|p| !p.immutable())
{ {
// That next check is expensive, that's why we have all the guards above.
let is_immutable = ty.is_freeze(*ecx.tcx, ecx.param_env);
let place = ecx.ref_to_mplace(val)?; let place = ecx.ref_to_mplace(val)?;
let new_place = place.map_provenance(CtfeProvenance::as_immutable); let new_place = if is_immutable {
place.map_provenance(CtfeProvenance::as_immutable)
} else {
// Even if it is not immutable, remember that it is a shared reference.
// This allows it to become part of the final value of the constant.
// (See <https://github.com/rust-lang/rust/pull/128543> for why we allow this
// even when there is interior mutability.)
place.map_provenance(CtfeProvenance::as_shared_ref)
};
Ok(ImmTy::from_immediate(new_place.to_ref(ecx), val.layout)) Ok(ImmTy::from_immediate(new_place.to_ref(ecx), val.layout))
} else { } else {
Ok(val.clone()) Ok(val.clone())

View File

@ -35,13 +35,10 @@ pub(crate) struct NestedStaticInThreadLocal {
pub span: Span, pub span: Span,
} }
#[derive(LintDiagnostic)] #[derive(Diagnostic)]
#[diag(const_eval_mutable_ptr_in_final)] #[diag(const_eval_mutable_ptr_in_final)]
pub(crate) struct MutablePtrInFinal { pub(crate) struct MutablePtrInFinal {
// rust-lang/rust#122153: This was marked as `#[primary_span]` under #[primary_span]
// `derive(Diagnostic)`. Since we expect we may hard-error in future, we are
// keeping the field (and skipping it under `derive(LintDiagnostic)`).
#[skip_arg]
pub span: Span, pub span: Span,
pub kind: InternKind, pub kind: InternKind,
} }

View File

@ -20,6 +20,7 @@ use rustc_hir as hir;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult}; use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult};
use rustc_middle::query::TyCtxtAt; use rustc_middle::query::TyCtxtAt;
use rustc_middle::span_bug;
use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::layout::TyAndLayout;
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_span::sym; use rustc_span::sym;
@ -223,37 +224,52 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
continue; continue;
} }
// Crucially, we check this *before* checking whether the `alloc_id` // Ensure that this is derived from a shared reference. Crucially, we check this *before*
// has already been interned. The point of this check is to ensure that when // checking whether the `alloc_id` has already been interned. The point of this check is to
// there are multiple pointers to the same allocation, they are *all* immutable. // ensure that when there are multiple pointers to the same allocation, they are *all*
// Therefore it would be bad if we only checked the first pointer to any given // derived from a shared reference. Therefore it would be bad if we only checked the first
// allocation. // pointer to any given allocation.
// (It is likely not possible to actually have multiple pointers to the same allocation, // (It is likely not possible to actually have multiple pointers to the same allocation,
// so alternatively we could also check that and ICE if there are multiple such pointers.) // so alternatively we could also check that and ICE if there are multiple such pointers.)
// See <https://github.com/rust-lang/rust/pull/128543> for why we are checking for "shared
// reference" and not "immutable", i.e., for why we are allowing interior-mutable shared
// references: they can actually be created in safe code while pointing to apparently
// "immutable" values, via promotion or tail expression lifetime extension of
// `&None::<Cell<T>>`.
// We also exclude promoteds from this as `&mut []` can be promoted, which is a mutable
// reference pointing to an immutable (zero-sized) allocation. We rely on the promotion
// analysis not screwing up to ensure that it is sound to intern promoteds as immutable.
if intern_kind != InternKind::Promoted if intern_kind != InternKind::Promoted
&& inner_mutability == Mutability::Not && inner_mutability == Mutability::Not
&& !prov.immutable() && !prov.shared_ref()
{ {
if ecx.tcx.try_get_global_alloc(alloc_id).is_some() let is_already_global = ecx.tcx.try_get_global_alloc(alloc_id).is_some();
&& !just_interned.contains(&alloc_id) if is_already_global && !just_interned.contains(&alloc_id) {
{
// This is a pointer to some memory from another constant. We encounter mutable // This is a pointer to some memory from another constant. We encounter mutable
// pointers to such memory since we do not always track immutability through // pointers to such memory since we do not always track immutability through
// these "global" pointers. Allowing them is harmless; the point of these checks // these "global" pointers. Allowing them is harmless; the point of these checks
// during interning is to justify why we intern the *new* allocations immutably, // during interning is to justify why we intern the *new* allocations immutably,
// so we can completely ignore existing allocations. We also don't need to add // so we can completely ignore existing allocations.
// this to the todo list, since after all it is already interned. // We can also skip the rest of this loop iteration, since after all it is already
// interned.
continue; continue;
} }
// Found a mutable pointer inside a const where inner allocations should be // If this is a dangling pointer, that's actually fine -- the problematic case is
// immutable. We exclude promoteds from this, since things like `&mut []` and // when there is memory there that someone might expect to be mutable, but we make it immutable.
// `&None::<Cell<i32>>` lead to promotion that can produce mutable pointers. We rely let dangling = !is_already_global && !ecx.memory.alloc_map.contains_key(&alloc_id);
// on the promotion analysis not screwing up to ensure that it is sound to intern if !dangling {
// promoteds as immutable. // Found a mutable reference inside a const where inner allocations should be
trace!("found bad mutable pointer"); // immutable.
// Prefer dangling pointer errors over mutable pointer errors if !ecx.tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you {
if result.is_ok() { span_bug!(
result = Err(InternResult::FoundBadMutablePointer); ecx.tcx.span,
"the static const safety checks accepted mutable references they should not have accepted"
);
}
// Prefer dangling pointer errors over mutable pointer errors
if result.is_ok() {
result = Err(InternResult::FoundBadMutablePointer);
}
} }
} }
if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { if ecx.tcx.try_get_global_alloc(alloc_id).is_some() {
@ -261,7 +277,6 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
debug_assert!(!ecx.memory.alloc_map.contains_key(&alloc_id)); debug_assert!(!ecx.memory.alloc_map.contains_key(&alloc_id));
continue; continue;
} }
just_interned.insert(alloc_id);
// We always intern with `inner_mutability`, and furthermore we ensured above that if // We always intern with `inner_mutability`, and furthermore we ensured above that if
// that is "immutable", then there are *no* mutable pointers anywhere in the newly // that is "immutable", then there are *no* mutable pointers anywhere in the newly
// interned memory -- justifying that we can indeed intern immutably. However this also // interned memory -- justifying that we can indeed intern immutably. However this also
@ -272,6 +287,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
// pointers before deciding which allocations can be made immutable; but for now we are // pointers before deciding which allocations can be made immutable; but for now we are
// okay with losing some potential for immutability here. This can anyway only affect // okay with losing some potential for immutability here. This can anyway only affect
// `static mut`. // `static mut`.
just_interned.insert(alloc_id);
match intern_shallow(ecx, alloc_id, inner_mutability) { match intern_shallow(ecx, alloc_id, inner_mutability) {
Ok(nested) => todo.extend(nested), Ok(nested) => todo.extend(nested),
Err(()) => { Err(()) => {

View File

@ -14,7 +14,6 @@ use hir::def::DefKind;
use rustc_ast::Mutability; use rustc_ast::Mutability;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_middle::bug;
use rustc_middle::mir::interpret::ValidationErrorKind::{self, *}; use rustc_middle::mir::interpret::ValidationErrorKind::{self, *};
use rustc_middle::mir::interpret::{ use rustc_middle::mir::interpret::{
alloc_range, ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance, alloc_range, ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
@ -22,6 +21,7 @@ use rustc_middle::mir::interpret::{
}; };
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::{sym, Symbol}; use rustc_span::symbol::{sym, Symbol};
use rustc_target::abi::{ use rustc_target::abi::{
Abi, FieldIdx, FieldsShape, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange, Abi, FieldIdx, FieldsShape, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
@ -617,6 +617,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
if ptr_expected_mutbl == Mutability::Mut if ptr_expected_mutbl == Mutability::Mut
&& alloc_actual_mutbl == Mutability::Not && alloc_actual_mutbl == Mutability::Not
{ {
if !self.ecx.tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you
{
span_bug!(
self.ecx.tcx.span,
"the static const safety checks accepted mutable references they should not have accepted"
);
}
throw_validation_failure!(self.path, MutableRefToImmutable); throw_validation_failure!(self.path, MutableRefToImmutable);
} }
// In a const, everything must be completely immutable. // In a const, everything must be completely immutable.

View File

@ -579,6 +579,10 @@ fn register_builtins(store: &mut LintStore) {
<https://github.com/rust-lang/rust/issues/107457> for more information", <https://github.com/rust-lang/rust/issues/107457> for more information",
); );
store.register_removed("writes_through_immutable_pointer", "converted into hard error"); store.register_removed("writes_through_immutable_pointer", "converted into hard error");
store.register_removed(
"const_eval_mutable_ptr_in_final_value",
"partially allowed now, otherwise turned into a hard error",
);
} }
fn register_internals(store: &mut LintStore) { fn register_internals(store: &mut LintStore) {

View File

@ -29,7 +29,6 @@ declare_lint_pass! {
CENUM_IMPL_DROP_CAST, CENUM_IMPL_DROP_CAST,
COHERENCE_LEAK_CHECK, COHERENCE_LEAK_CHECK,
CONFLICTING_REPR_HINTS, CONFLICTING_REPR_HINTS,
CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
CONST_EVALUATABLE_UNCHECKED, CONST_EVALUATABLE_UNCHECKED,
CONST_ITEM_MUTATION, CONST_ITEM_MUTATION,
DEAD_CODE, DEAD_CODE,
@ -2804,51 +2803,6 @@ declare_lint! {
@feature_gate = strict_provenance; @feature_gate = strict_provenance;
} }
declare_lint! {
/// The `const_eval_mutable_ptr_in_final_value` lint detects if a mutable pointer
/// has leaked into the final value of a const expression.
///
/// ### Example
///
/// ```rust
/// pub enum JsValue {
/// Undefined,
/// Object(std::cell::Cell<bool>),
/// }
///
/// impl ::std::ops::Drop for JsValue {
/// fn drop(&mut self) {}
/// }
///
/// const UNDEFINED: &JsValue = &JsValue::Undefined;
///
/// fn main() {
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// In the 1.77 release, the const evaluation machinery adopted some
/// stricter rules to reject expressions with values that could
/// end up holding mutable references to state stored in static memory
/// (which is inherently immutable).
///
/// This is a [future-incompatible] lint to ease the transition to an error.
/// See [issue #122153] for more details.
///
/// [issue #122153]: https://github.com/rust-lang/rust/issues/122153
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
Warn,
"detects a mutable pointer that has leaked into final value of a const expression",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reference: "issue #122153 <https://github.com/rust-lang/rust/issues/122153>",
};
}
declare_lint! { declare_lint! {
/// The `const_evaluatable_unchecked` lint detects a generic constant used /// The `const_evaluatable_unchecked` lint detects a generic constant used
/// in a type. /// in a type.

View File

@ -80,14 +80,23 @@ pub trait Provenance: Copy + fmt::Debug + 'static {
} }
/// The type of provenance in the compile-time interpreter. /// The type of provenance in the compile-time interpreter.
/// This is a packed representation of an `AllocId` and an `immutable: bool`. /// This is a packed representation of:
/// - an `AllocId` (non-zero)
/// - an `immutable: bool`
/// - a `shared_ref: bool`
///
/// with the extra invariant that if `immutable` is `true`, then so
/// is `shared_ref`.
#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] #[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct CtfeProvenance(NonZero<u64>); pub struct CtfeProvenance(NonZero<u64>);
impl From<AllocId> for CtfeProvenance { impl From<AllocId> for CtfeProvenance {
fn from(value: AllocId) -> Self { fn from(value: AllocId) -> Self {
let prov = CtfeProvenance(value.0); let prov = CtfeProvenance(value.0);
assert!(!prov.immutable(), "`AllocId` with the highest bit set cannot be used in CTFE"); assert!(
prov.alloc_id() == value,
"`AllocId` with the highest bits set cannot be used in CTFE"
);
prov prov
} }
} }
@ -103,12 +112,14 @@ impl fmt::Debug for CtfeProvenance {
} }
const IMMUTABLE_MASK: u64 = 1 << 63; // the highest bit const IMMUTABLE_MASK: u64 = 1 << 63; // the highest bit
const SHARED_REF_MASK: u64 = 1 << 62;
const ALLOC_ID_MASK: u64 = u64::MAX & !IMMUTABLE_MASK & !SHARED_REF_MASK;
impl CtfeProvenance { impl CtfeProvenance {
/// Returns the `AllocId` of this provenance. /// Returns the `AllocId` of this provenance.
#[inline(always)] #[inline(always)]
pub fn alloc_id(self) -> AllocId { pub fn alloc_id(self) -> AllocId {
AllocId(NonZero::new(self.0.get() & !IMMUTABLE_MASK).unwrap()) AllocId(NonZero::new(self.0.get() & ALLOC_ID_MASK).unwrap())
} }
/// Returns whether this provenance is immutable. /// Returns whether this provenance is immutable.
@ -117,10 +128,38 @@ impl CtfeProvenance {
self.0.get() & IMMUTABLE_MASK != 0 self.0.get() & IMMUTABLE_MASK != 0
} }
/// Returns whether this provenance is derived from a shared reference.
#[inline]
pub fn shared_ref(self) -> bool {
self.0.get() & SHARED_REF_MASK != 0
}
pub fn into_parts(self) -> (AllocId, bool, bool) {
(self.alloc_id(), self.immutable(), self.shared_ref())
}
pub fn from_parts((alloc_id, immutable, shared_ref): (AllocId, bool, bool)) -> Self {
let prov = CtfeProvenance::from(alloc_id);
if immutable {
// This sets both flags, so we don't even have to check `shared_ref`.
prov.as_immutable()
} else if shared_ref {
prov.as_shared_ref()
} else {
prov
}
}
/// Returns an immutable version of this provenance. /// Returns an immutable version of this provenance.
#[inline] #[inline]
pub fn as_immutable(self) -> Self { pub fn as_immutable(self) -> Self {
CtfeProvenance(self.0 | IMMUTABLE_MASK) CtfeProvenance(self.0 | IMMUTABLE_MASK | SHARED_REF_MASK)
}
/// Returns a "shared reference" (but not necessarily immutable!) version of this provenance.
#[inline]
pub fn as_shared_ref(self) -> Self {
CtfeProvenance(self.0 | SHARED_REF_MASK)
} }
} }

View File

@ -165,8 +165,7 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AllocId {
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for CtfeProvenance { impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for CtfeProvenance {
fn encode(&self, e: &mut E) { fn encode(&self, e: &mut E) {
self.alloc_id().encode(e); self.into_parts().encode(e);
self.immutable().encode(e);
} }
} }
@ -295,10 +294,8 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AllocId {
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for CtfeProvenance { impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for CtfeProvenance {
fn decode(decoder: &mut D) -> Self { fn decode(decoder: &mut D) -> Self {
let alloc_id: AllocId = Decodable::decode(decoder); let parts = Decodable::decode(decoder);
let prov = CtfeProvenance::from(alloc_id); CtfeProvenance::from_parts(parts)
let immutable: bool = Decodable::decode(decoder);
if immutable { prov.as_immutable() } else { prov }
} }
} }

View File

@ -75,11 +75,9 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
} }
} }
// CtfeProvenance is an AllocId and a bool.
impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::CtfeProvenance { impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::CtfeProvenance {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
self.alloc_id().hash_stable(hcx, hasher); self.into_parts().hash_stable(hcx, hasher);
self.immutable().hash_stable(hcx, hasher);
} }
} }

View File

@ -0,0 +1,11 @@
// Version of `tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs` without the flag that
// suppresses the ICE.
//@ known-bug: #129233
#![feature(core_intrinsics)]
#![feature(const_heap)]
#![feature(const_mut_refs)]
use std::intrinsics;
const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 };
fn main() {}

View File

@ -1,11 +1,12 @@
// We unleash Miri here since this test demonstrates code that bypasses the checks against interning
// mutable pointers, which currently ICEs. Unleashing Miri silence the ICE.
//@ compile-flags: -Zunleash-the-miri-inside-of-you
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(const_heap)] #![feature(const_heap)]
#![feature(const_mut_refs)] #![feature(const_mut_refs)]
#![deny(const_eval_mutable_ptr_in_final_value)]
use std::intrinsics; use std::intrinsics;
const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 };
//~^ error: mutable pointer in final value of constant //~^ error: mutable pointer in final value of constant
//~| WARNING this was previously accepted by the compiler
fn main() {} fn main() {}

View File

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

View File

@ -1,18 +0,0 @@
//@ check-pass
use std::cell::Cell;
pub enum JsValue {
Undefined,
Object(Cell<bool>),
}
impl ::std::ops::Drop for JsValue {
fn drop(&mut self) {}
}
const UNDEFINED: &JsValue = &JsValue::Undefined;
//~^ WARN encountered mutable pointer in final value of constant
//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
fn main() {
}

View File

@ -1,23 +0,0 @@
warning: encountered mutable pointer in final value of constant
--> $DIR/future-incompat-mutable-in-final-value-issue-121610.rs:13:1
|
LL | const UNDEFINED: &JsValue = &JsValue::Undefined;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
= note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default
warning: 1 warning emitted
Future incompatibility report: Future breakage diagnostic:
warning: encountered mutable pointer in final value of constant
--> $DIR/future-incompat-mutable-in-final-value-issue-121610.rs:13:1
|
LL | const UNDEFINED: &JsValue = &JsValue::Undefined;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
= note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default

View File

@ -3,7 +3,6 @@
//@ normalize-stderr-test: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP" //@ normalize-stderr-test: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
#![allow(static_mut_refs)] #![allow(static_mut_refs)]
#![deny(const_eval_mutable_ptr_in_final_value)]
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::sync::atomic::*; use std::sync::atomic::*;
@ -18,13 +17,11 @@ static OH_YES: &mut i32 = &mut 42;
//~| pointing to read-only memory //~| pointing to read-only memory
static BAR: &mut () = &mut (); static BAR: &mut () = &mut ();
//~^ ERROR encountered mutable pointer in final value of static //~^ ERROR encountered mutable pointer in final value of static
//~| WARNING this was previously accepted by the compiler
struct Foo<T>(T); struct Foo<T>(T);
static BOO: &mut Foo<()> = &mut Foo(()); static BOO: &mut Foo<()> = &mut Foo(());
//~^ ERROR encountered mutable pointer in final value of static //~^ ERROR encountered mutable pointer in final value of static
//~| WARNING this was previously accepted by the compiler
const BLUNT: &mut i32 = &mut 42; const BLUNT: &mut i32 = &mut 42;
//~^ ERROR: it is undefined behavior to use this value //~^ ERROR: it is undefined behavior to use this value
@ -81,36 +78,32 @@ const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _;
//~^ ERROR: mutable pointer in final value //~^ ERROR: mutable pointer in final value
//~| WARNING this was previously accepted by the compiler
const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _;
//~^ ERROR: mutable pointer in final value //~^ ERROR: mutable pointer in final value
//~| WARNING this was previously accepted by the compiler
// This does *not* error since it uses a shared reference, and we have to ignore
// those. See <https://github.com/rust-lang/rust/pull/128543>.
const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
//~^ ERROR: mutable pointer in final value
//~| WARNING this was previously accepted by the compiler
struct SyncPtr<T> { struct SyncPtr<T> {
x: *const T, x: *const T,
} }
unsafe impl<T> Sync for SyncPtr<T> {} unsafe impl<T> Sync for SyncPtr<T> {}
// These pass the lifetime checks because of the "tail expression" / "outer scope" rule. // These pass the lifetime checks because of the "tail expression" / "outer scope" rule. (This
// (This relies on `SyncPtr` being a curly brace struct.) // relies on `SyncPtr` being a curly brace struct.) However, we intern the inner memory as
// However, we intern the inner memory as read-only, so this must be rejected. // read-only, so ideally this should be rejected. Unfortunately, as explained in
// <https://github.com/rust-lang/rust/pull/128543>, we have to accept it.
// (Also see `static-no-inner-mut` for similar tests on `static`.) // (Also see `static-no-inner-mut` for similar tests on `static`.)
const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) }; const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
//~^ ERROR mutable pointer in final value
//~| WARNING this was previously accepted by the compiler
// With mutable references at least, we can detect this and error.
const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ }; const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ };
//~^ ERROR mutable pointer in final value //~^ ERROR mutable pointer in final value
//~| WARNING this was previously accepted by the compiler
const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 }; const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
//~^ ERROR mutable pointer in final value //~^ ERROR mutable pointer in final value
//~| WARNING this was previously accepted by the compiler
fn main() { fn main() {

View File

@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:13:1 --> $DIR/mutable_references.rs:12:1
| |
LL | static FOO: &&mut u32 = &&mut 42; LL | static FOO: &&mut u32 = &&mut 42;
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered mutable reference or box pointing to read-only memory | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered mutable reference or box pointing to read-only memory
@ -10,7 +10,7 @@ LL | static FOO: &&mut u32 = &&mut 42;
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:16:1 --> $DIR/mutable_references.rs:15:1
| |
LL | static OH_YES: &mut i32 = &mut 42; LL | static OH_YES: &mut i32 = &mut 42;
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
@ -21,30 +21,19 @@ LL | static OH_YES: &mut i32 = &mut 42;
} }
error: encountered mutable pointer in final value of static error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:19:1 --> $DIR/mutable_references.rs:18:1
| |
LL | static BAR: &mut () = &mut (); LL | static BAR: &mut () = &mut ();
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/mutable_references.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: encountered mutable pointer in final value of static error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:25:1 --> $DIR/mutable_references.rs:23:1
| |
LL | static BOO: &mut Foo<()> = &mut Foo(()); LL | static BOO: &mut Foo<()> = &mut Foo(());
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:29:1 --> $DIR/mutable_references.rs:26:1
| |
LL | const BLUNT: &mut i32 = &mut 42; LL | const BLUNT: &mut i32 = &mut 42;
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
@ -55,7 +44,7 @@ LL | const BLUNT: &mut i32 = &mut 42;
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:33:1 --> $DIR/mutable_references.rs:30:1
| |
LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC }; LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC };
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
@ -66,7 +55,7 @@ LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC }
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:43:1 --> $DIR/mutable_references.rs:40:1
| |
LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^ constructing invalid value at .x.<deref>: encountered `UnsafeCell` in read-only memory | ^^^^^^^^^^^^^^^ constructing invalid value at .x.<deref>: encountered `UnsafeCell` in read-only memory
@ -77,7 +66,7 @@ LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:49:1 --> $DIR/mutable_references.rs:46:1
| |
LL | const MUH: Meh = Meh { LL | const MUH: Meh = Meh {
| ^^^^^^^^^^^^^^ constructing invalid value at .x.<deref>: encountered `UnsafeCell` in read-only memory | ^^^^^^^^^^^^^^ constructing invalid value at .x.<deref>: encountered `UnsafeCell` in read-only memory
@ -88,7 +77,7 @@ LL | const MUH: Meh = Meh {
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:61:1 --> $DIR/mutable_references.rs:58:1
| |
LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>.x: encountered `UnsafeCell` in read-only memory | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>.x: encountered `UnsafeCell` in read-only memory
@ -99,7 +88,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:68:1 --> $DIR/mutable_references.rs:65:1
| |
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
@ -110,7 +99,7 @@ LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:75:1 --> $DIR/mutable_references.rs:72:1
| |
LL | const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE }; LL | const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
@ -121,67 +110,37 @@ LL | const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE };
} }
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/mutable_references.rs:78:43 --> $DIR/mutable_references.rs:75:43
| |
LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
| ^^^^^^^^^^^^^ constant accesses mutable global memory | ^^^^^^^^^^^^^ constant accesses mutable global memory
error: encountered mutable pointer in final value of constant error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:82:1 --> $DIR/mutable_references.rs:79:1
| |
LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
error: encountered mutable pointer in final value of constant error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:86:1 --> $DIR/mutable_references.rs:82:1
| |
LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
error: encountered mutable pointer in final value of constant error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:90:1 --> $DIR/mutable_references.rs:102:1
|
LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:103:1
|
LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:107:1
| |
LL | const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ }; LL | const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
error: encountered mutable pointer in final value of constant error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:111:1 --> $DIR/mutable_references.rs:105:1
| |
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 }; LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item
--> $DIR/mutable_references.rs:120:5 --> $DIR/mutable_references.rs:113:5
| |
LL | *OH_YES = 99; LL | *OH_YES = 99;
| ^^^^^^^^^^^^ cannot assign | ^^^^^^^^^^^^ cannot assign
@ -189,227 +148,107 @@ LL | *OH_YES = 99;
warning: skipping const checks warning: skipping const checks
| |
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:13:26 --> $DIR/mutable_references.rs:12:26
| |
LL | static FOO: &&mut u32 = &&mut 42; LL | static FOO: &&mut u32 = &&mut 42;
| ^^^^^^^ | ^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:16:27 --> $DIR/mutable_references.rs:15:27
| |
LL | static OH_YES: &mut i32 = &mut 42; LL | static OH_YES: &mut i32 = &mut 42;
| ^^^^^^^ | ^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:19:23 --> $DIR/mutable_references.rs:18:23
| |
LL | static BAR: &mut () = &mut (); LL | static BAR: &mut () = &mut ();
| ^^^^^^^ | ^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:25:28 --> $DIR/mutable_references.rs:23:28
| |
LL | static BOO: &mut Foo<()> = &mut Foo(()); LL | static BOO: &mut Foo<()> = &mut Foo(());
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:29:25 --> $DIR/mutable_references.rs:26:25
| |
LL | const BLUNT: &mut i32 = &mut 42; LL | const BLUNT: &mut i32 = &mut 42;
| ^^^^^^^ | ^^^^^^^
help: skipping check for `const_refs_to_static` feature help: skipping check for `const_refs_to_static` feature
--> $DIR/mutable_references.rs:33:68 --> $DIR/mutable_references.rs:30:68
| |
LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC }; LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC };
| ^^^^^^ | ^^^^^^
help: skipping check for `const_mut_refs` feature help: skipping check for `const_mut_refs` feature
--> $DIR/mutable_references.rs:33:63 --> $DIR/mutable_references.rs:30:63
| |
LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC }; LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC };
| ^^^^^^^^^^^ | ^^^^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:43:28 --> $DIR/mutable_references.rs:40:28
| |
LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:52:8 --> $DIR/mutable_references.rs:49:8
| |
LL | x: &UnsafeCell::new(42), LL | x: &UnsafeCell::new(42),
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:61:27 --> $DIR/mutable_references.rs:58:27
| |
LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check for `const_mut_refs` feature help: skipping check for `const_mut_refs` feature
--> $DIR/mutable_references.rs:68:49 --> $DIR/mutable_references.rs:65:49
| |
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check for `const_mut_refs` feature help: skipping check for `const_mut_refs` feature
--> $DIR/mutable_references.rs:68:49 --> $DIR/mutable_references.rs:65:49
| |
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check for `const_refs_to_static` feature help: skipping check for `const_refs_to_static` feature
--> $DIR/mutable_references.rs:75:43 --> $DIR/mutable_references.rs:72:43
| |
LL | const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE }; LL | const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE };
| ^^^^^^^ | ^^^^^^^
help: skipping check for `const_refs_to_static` feature help: skipping check for `const_refs_to_static` feature
--> $DIR/mutable_references.rs:78:45 --> $DIR/mutable_references.rs:75:45
| |
LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
| ^^^^^^^^^^^ | ^^^^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:82:45 --> $DIR/mutable_references.rs:79:45
| |
LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _;
| ^^^^^^^ | ^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:86:46 --> $DIR/mutable_references.rs:82:46
| |
LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _;
| ^^^^^^^ | ^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:90:47 --> $DIR/mutable_references.rs:87:47
| |
LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:103:51 --> $DIR/mutable_references.rs:99:51
| |
LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) }; LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:107:49 --> $DIR/mutable_references.rs:102:49
| |
LL | const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ }; LL | const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ };
| ^^^^^^^ | ^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:111:51 --> $DIR/mutable_references.rs:105:51
| |
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 }; LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
| ^^^^^^ | ^^^^^^
error: aborting due to 19 previous errors; 1 warning emitted error: aborting due to 17 previous errors; 1 warning emitted
Some errors have detailed explanations: E0080, E0594. Some errors have detailed explanations: E0080, E0594.
For more information about an error, try `rustc --explain E0080`. For more information about an error, try `rustc --explain E0080`.
Future incompatibility report: Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:19:1
|
LL | static BAR: &mut () = &mut ();
| ^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/mutable_references.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:25:1
|
LL | static BOO: &mut Foo<()> = &mut Foo(());
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/mutable_references.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Future breakage diagnostic:
error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:82:1
|
LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/mutable_references.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Future breakage diagnostic:
error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:86:1
|
LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/mutable_references.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Future breakage diagnostic:
error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:90:1
|
LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/mutable_references.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Future breakage diagnostic:
error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:103:1
|
LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/mutable_references.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Future breakage diagnostic:
error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:107:1
|
LL | const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/mutable_references.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Future breakage diagnostic:
error: encountered mutable pointer in final value of constant
--> $DIR/mutable_references.rs:111:1
|
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/mutable_references.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/static-no-inner-mut.rs:9:1 --> $DIR/static-no-inner-mut.rs:8:1
| |
LL | static REF: &AtomicI32 = &AtomicI32::new(42); LL | static REF: &AtomicI32 = &AtomicI32::new(42);
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory
@ -10,7 +10,7 @@ LL | static REF: &AtomicI32 = &AtomicI32::new(42);
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/static-no-inner-mut.rs:12:1 --> $DIR/static-no-inner-mut.rs:11:1
| |
LL | static REFMUT: &mut i32 = &mut 0; LL | static REFMUT: &mut i32 = &mut 0;
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
@ -21,7 +21,7 @@ LL | static REFMUT: &mut i32 = &mut 0;
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/static-no-inner-mut.rs:16:1 --> $DIR/static-no-inner-mut.rs:15:1
| |
LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory | ^^^^^^^^^^^^^^^^^^^^^^^ 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}};
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/static-no-inner-mut.rs:18:1 --> $DIR/static-no-inner-mut.rs:17:1
| |
LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | ^^^^^^^^^^^^^^^^^^^^^^^^ 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}};
error: encountered mutable pointer in final value of static error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:34:1 --> $DIR/static-no-inner-mut.rs:34:1
| |
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/static-no-inner-mut.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:38:1
|
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ }; LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
error: encountered mutable pointer in final value of static error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:42:1 --> $DIR/static-no-inner-mut.rs:37:1
| |
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 }; LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
warning: skipping const checks warning: skipping const checks
| |
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:9:26 --> $DIR/static-no-inner-mut.rs:8:26
| |
LL | static REF: &AtomicI32 = &AtomicI32::new(42); LL | static REF: &AtomicI32 = &AtomicI32::new(42);
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:12:27 --> $DIR/static-no-inner-mut.rs:11:27
| |
LL | static REFMUT: &mut i32 = &mut 0; LL | static REFMUT: &mut i32 = &mut 0;
| ^^^^^^ | ^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:16:56 --> $DIR/static-no-inner-mut.rs:15:56
| |
LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
| ^^^^ | ^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:18:44 --> $DIR/static-no-inner-mut.rs:17:44
| |
LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
| ^^^^^^^^ | ^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:34:52 --> $DIR/static-no-inner-mut.rs:31:52
| |
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) }; LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:38:51 --> $DIR/static-no-inner-mut.rs:34:51
| |
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ }; LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
| ^^^^^^^ | ^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:42:52 --> $DIR/static-no-inner-mut.rs:37:52
| |
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 }; LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
| ^^^^^^ | ^^^^^^
error: aborting due to 7 previous errors; 1 warning emitted error: aborting due to 6 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0080`. For more information about this error, try `rustc --explain E0080`.
Future incompatibility report: Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:34:1
|
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/static-no-inner-mut.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:38:1
|
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/static-no-inner-mut.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:42:1
|
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/static-no-inner-mut.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/static-no-inner-mut.rs:9:1 --> $DIR/static-no-inner-mut.rs:8:1
| |
LL | static REF: &AtomicI32 = &AtomicI32::new(42); LL | static REF: &AtomicI32 = &AtomicI32::new(42);
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory
@ -10,7 +10,7 @@ LL | static REF: &AtomicI32 = &AtomicI32::new(42);
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/static-no-inner-mut.rs:12:1 --> $DIR/static-no-inner-mut.rs:11:1
| |
LL | static REFMUT: &mut i32 = &mut 0; LL | static REFMUT: &mut i32 = &mut 0;
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
@ -21,7 +21,7 @@ LL | static REFMUT: &mut i32 = &mut 0;
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/static-no-inner-mut.rs:16:1 --> $DIR/static-no-inner-mut.rs:15:1
| |
LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory | ^^^^^^^^^^^^^^^^^^^^^^^ 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}};
} }
error[E0080]: it is undefined behavior to use this value error[E0080]: it is undefined behavior to use this value
--> $DIR/static-no-inner-mut.rs:18:1 --> $DIR/static-no-inner-mut.rs:17:1
| |
LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | ^^^^^^^^^^^^^^^^^^^^^^^^ 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}};
error: encountered mutable pointer in final value of static error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:34:1 --> $DIR/static-no-inner-mut.rs:34:1
| |
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/static-no-inner-mut.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:38:1
|
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ }; LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
error: encountered mutable pointer in final value of static error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:42:1 --> $DIR/static-no-inner-mut.rs:37:1
| |
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 }; LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
warning: skipping const checks warning: skipping const checks
| |
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:9:26 --> $DIR/static-no-inner-mut.rs:8:26
| |
LL | static REF: &AtomicI32 = &AtomicI32::new(42); LL | static REF: &AtomicI32 = &AtomicI32::new(42);
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:12:27 --> $DIR/static-no-inner-mut.rs:11:27
| |
LL | static REFMUT: &mut i32 = &mut 0; LL | static REFMUT: &mut i32 = &mut 0;
| ^^^^^^ | ^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:16:56 --> $DIR/static-no-inner-mut.rs:15:56
| |
LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
| ^^^^ | ^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:18:44 --> $DIR/static-no-inner-mut.rs:17:44
| |
LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
| ^^^^^^^^ | ^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:34:52 --> $DIR/static-no-inner-mut.rs:31:52
| |
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) }; LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:38:51 --> $DIR/static-no-inner-mut.rs:34:51
| |
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ }; LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
| ^^^^^^^ | ^^^^^^^
help: skipping check that does not even have a feature gate help: skipping check that does not even have a feature gate
--> $DIR/static-no-inner-mut.rs:42:52 --> $DIR/static-no-inner-mut.rs:37:52
| |
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 }; LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
| ^^^^^^ | ^^^^^^
error: aborting due to 7 previous errors; 1 warning emitted error: aborting due to 6 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0080`. For more information about this error, try `rustc --explain E0080`.
Future incompatibility report: Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:34:1
|
LL | static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/static-no-inner-mut.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:38:1
|
LL | static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/static-no-inner-mut.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/static-no-inner-mut.rs:42:1
|
LL | static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/static-no-inner-mut.rs:6:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -3,7 +3,6 @@
#![feature(const_refs_to_cell, const_mut_refs)] #![feature(const_refs_to_cell, const_mut_refs)]
// All "inner" allocations that come with a `static` are interned immutably. This means it is // All "inner" allocations that come with a `static` are interned immutably. This means it is
// crucial that we do not accept any form of (interior) mutability there. // crucial that we do not accept any form of (interior) mutability there.
#![deny(const_eval_mutable_ptr_in_final_value)]
use std::sync::atomic::*; use std::sync::atomic::*;
static REF: &AtomicI32 = &AtomicI32::new(42); static REF: &AtomicI32 = &AtomicI32::new(42);
@ -27,20 +26,15 @@ unsafe impl<T> Sync for SyncPtr<T> {}
// All of these pass the lifetime checks because of the "tail expression" / "outer scope" rule. // All of these pass the lifetime checks because of the "tail expression" / "outer scope" rule.
// (This relies on `SyncPtr` being a curly brace struct.) // (This relies on `SyncPtr` being a curly brace struct.)
// Then they get interned immutably, which is not great. // Then they get interned immutably, which is not great. See
// `mut_ref_in_final.rs` and `std/cell.rs` ensure that we don't accept this even with the feature // <https://github.com/rust-lang/rust/pull/128543> for why we accept such code.
// fate, but for unleashed Miri there's not really any way we can reject them: it's just
// non-dangling raw pointers.
static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) }; static RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
//~^ ERROR mutable pointer in final value
//~| WARNING this was previously accepted by the compiler
// With mutable references at least, we can detect this and error.
static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ }; static RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x : &mut 42 as *mut _ as *const _ };
//~^ ERROR mutable pointer in final value //~^ ERROR mutable pointer in final value
//~| WARNING this was previously accepted by the compiler
static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 }; static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
//~^ ERROR mutable pointer in final value //~^ ERROR mutable pointer in final value
//~| WARNING this was previously accepted by the compiler
fn main() {} fn main() {}

View File

@ -18,8 +18,8 @@ const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
// This one does not get promoted because of `Drop`, and then enters interesting codepaths because // This one does not get promoted because of `Drop`, and then enters interesting codepaths because
// as a value it has no interior mutability, but as a type it does. See // as a value it has no interior mutability, but as a type it does. See
// <https://github.com/rust-lang/rust/issues/121610>. Value-based reasoning for interior mutability // <https://github.com/rust-lang/rust/issues/121610>. Value-based reasoning for interior mutability
// is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) so for now we // is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) but we've
// reject this, though not with a great error message. // done it since Rust 1.0 so we can't stop now.
pub enum JsValue { pub enum JsValue {
Undefined, Undefined,
Object(Cell<bool>), Object(Cell<bool>),
@ -28,10 +28,8 @@ impl Drop for JsValue {
fn drop(&mut self) {} fn drop(&mut self) {}
} }
const UNDEFINED: &JsValue = &JsValue::Undefined; const UNDEFINED: &JsValue = &JsValue::Undefined;
//~^ WARNING: mutable pointer in final value of constant
//~| WARNING: this was previously accepted by the compiler but is being phased out
// In contrast, this one works since it is being promoted. // Here's a variant of the above that uses promotion instead of the "outer scope" rule.
const NONE: &'static Option<Cell<i32>> = &None; const NONE: &'static Option<Cell<i32>> = &None;
// Making it clear that this is promotion, not "outer scope". // Making it clear that this is promotion, not "outer scope".
const NONE_EXPLICIT_PROMOTED: &'static Option<Cell<i32>> = { const NONE_EXPLICIT_PROMOTED: &'static Option<Cell<i32>> = {

View File

@ -12,27 +12,6 @@ error[E0492]: constants cannot refer to interior mutable data
LL | const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) }; LL | const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
| ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value | ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value
warning: encountered mutable pointer in final value of constant error: aborting due to 2 previous errors
--> $DIR/refs-to-cell-in-final.rs:30:1
|
LL | const UNDEFINED: &JsValue = &JsValue::Undefined;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
= note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default
error: aborting due to 2 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0492`. For more information about this error, try `rustc --explain E0492`.
Future incompatibility report: Future breakage diagnostic:
warning: encountered mutable pointer in final value of constant
--> $DIR/refs-to-cell-in-final.rs:30:1
|
LL | const UNDEFINED: &JsValue = &JsValue::Undefined;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
= note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default