mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
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:
commit
9b72238eb8
@ -538,8 +538,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
// final value.
|
||||
// Note: This is only sound if every local that has a `StorageDead` has a
|
||||
// `StorageDead` in every control flow path leading to a `return` terminator.
|
||||
// The good news is that interning will detect if any unexpected mutable
|
||||
// pointer slips through.
|
||||
// If anything slips through, there's no safety net -- safe code can create
|
||||
// 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) {
|
||||
self.check_op(ops::TransientCellBorrow);
|
||||
} else {
|
||||
|
@ -10,7 +10,6 @@ use rustc_middle::traits::Reveal;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi::{self, Abi};
|
||||
@ -18,13 +17,12 @@ use tracing::{debug, instrument, trace};
|
||||
|
||||
use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
|
||||
use crate::const_eval::CheckAlignment;
|
||||
use crate::errors::{self, ConstEvalError, DanglingPtrInFinal};
|
||||
use crate::interpret::{
|
||||
create_static_alloc, eval_nullary_intrinsic, intern_const_alloc_recursive, throw_exhaust,
|
||||
CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpError,
|
||||
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
|
||||
#[instrument(level = "trace", skip(ecx, body))]
|
||||
@ -100,18 +98,15 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
|
||||
return Err(ecx
|
||||
.tcx
|
||||
.dcx()
|
||||
.emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind })
|
||||
.emit_err(errors::DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind })
|
||||
.into());
|
||||
}
|
||||
Err(InternResult::FoundBadMutablePointer) => {
|
||||
// only report mutable pointers if there were no dangling pointers
|
||||
let err_diag = errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind };
|
||||
ecx.tcx.emit_node_span_lint(
|
||||
lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
|
||||
ecx.machine.best_lint_scope(*ecx.tcx),
|
||||
err_diag.span,
|
||||
err_diag,
|
||||
)
|
||||
return Err(ecx
|
||||
.tcx
|
||||
.dcx()
|
||||
.emit_err(errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind })
|
||||
.into());
|
||||
}
|
||||
}
|
||||
|
||||
@ -443,7 +438,12 @@ fn report_eval_error<'tcx>(
|
||||
error,
|
||||
DUMMY_SP,
|
||||
|| 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,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -718,16 +718,29 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
|
||||
_kind: mir::RetagKind,
|
||||
val: &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.)
|
||||
if let ty::Ref(_, ty, mutbl) = val.layout.ty.kind()
|
||||
&& *mutbl == Mutability::Not
|
||||
&& val.to_scalar_and_meta().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.
|
||||
&& ty.is_freeze(*ecx.tcx, ecx.param_env)
|
||||
&& val
|
||||
.to_scalar_and_meta()
|
||||
.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 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))
|
||||
} else {
|
||||
Ok(val.clone())
|
||||
|
@ -35,13 +35,10 @@ pub(crate) struct NestedStaticInThreadLocal {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval_mutable_ptr_in_final)]
|
||||
pub(crate) struct MutablePtrInFinal {
|
||||
// rust-lang/rust#122153: This was marked as `#[primary_span]` under
|
||||
// `derive(Diagnostic)`. Since we expect we may hard-error in future, we are
|
||||
// keeping the field (and skipping it under `derive(LintDiagnostic)`).
|
||||
#[skip_arg]
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub kind: InternKind,
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ use rustc_hir as hir;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult};
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::sym;
|
||||
@ -223,37 +224,52 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
|
||||
continue;
|
||||
}
|
||||
|
||||
// Crucially, we check this *before* checking whether the `alloc_id`
|
||||
// has already been interned. The point of this check is to ensure that when
|
||||
// there are multiple pointers to the same allocation, they are *all* immutable.
|
||||
// Therefore it would be bad if we only checked the first pointer to any given
|
||||
// allocation.
|
||||
// Ensure that this is derived from a shared reference. Crucially, we check this *before*
|
||||
// checking whether the `alloc_id` has already been interned. The point of this check is to
|
||||
// ensure that when there are multiple pointers to the same allocation, they are *all*
|
||||
// derived from a shared reference. Therefore it would be bad if we only checked the first
|
||||
// pointer to any given 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.)
|
||||
// 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
|
||||
&& inner_mutability == Mutability::Not
|
||||
&& !prov.immutable()
|
||||
&& !prov.shared_ref()
|
||||
{
|
||||
if ecx.tcx.try_get_global_alloc(alloc_id).is_some()
|
||||
&& !just_interned.contains(&alloc_id)
|
||||
{
|
||||
let is_already_global = ecx.tcx.try_get_global_alloc(alloc_id).is_some();
|
||||
if is_already_global && !just_interned.contains(&alloc_id) {
|
||||
// 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
|
||||
// these "global" pointers. Allowing them is harmless; the point of these checks
|
||||
// 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
|
||||
// this to the todo list, since after all it is already interned.
|
||||
// so we can completely ignore existing allocations.
|
||||
// We can also skip the rest of this loop iteration, since after all it is already
|
||||
// interned.
|
||||
continue;
|
||||
}
|
||||
// Found a mutable pointer inside a const where inner allocations should be
|
||||
// immutable. We exclude promoteds from this, since things like `&mut []` and
|
||||
// `&None::<Cell<i32>>` lead to promotion that can produce mutable pointers. We rely
|
||||
// on the promotion analysis not screwing up to ensure that it is sound to intern
|
||||
// promoteds as immutable.
|
||||
trace!("found bad mutable pointer");
|
||||
// Prefer dangling pointer errors over mutable pointer errors
|
||||
if result.is_ok() {
|
||||
result = Err(InternResult::FoundBadMutablePointer);
|
||||
// If this is a dangling pointer, that's actually fine -- the problematic case is
|
||||
// when there is memory there that someone might expect to be mutable, but we make it immutable.
|
||||
let dangling = !is_already_global && !ecx.memory.alloc_map.contains_key(&alloc_id);
|
||||
if !dangling {
|
||||
// Found a mutable reference inside a const where inner allocations should be
|
||||
// immutable.
|
||||
if !ecx.tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you {
|
||||
span_bug!(
|
||||
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() {
|
||||
@ -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));
|
||||
continue;
|
||||
}
|
||||
just_interned.insert(alloc_id);
|
||||
// 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
|
||||
// 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
|
||||
// okay with losing some potential for immutability here. This can anyway only affect
|
||||
// `static mut`.
|
||||
just_interned.insert(alloc_id);
|
||||
match intern_shallow(ecx, alloc_id, inner_mutability) {
|
||||
Ok(nested) => todo.extend(nested),
|
||||
Err(()) => {
|
||||
|
@ -14,7 +14,6 @@ use hir::def::DefKind;
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::interpret::ValidationErrorKind::{self, *};
|
||||
use rustc_middle::mir::interpret::{
|
||||
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::{self, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_target::abi::{
|
||||
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
|
||||
&& 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);
|
||||
}
|
||||
// In a const, everything must be completely immutable.
|
||||
|
@ -579,6 +579,10 @@ fn register_builtins(store: &mut LintStore) {
|
||||
<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(
|
||||
"const_eval_mutable_ptr_in_final_value",
|
||||
"partially allowed now, otherwise turned into a hard error",
|
||||
);
|
||||
}
|
||||
|
||||
fn register_internals(store: &mut LintStore) {
|
||||
|
@ -29,7 +29,6 @@ declare_lint_pass! {
|
||||
CENUM_IMPL_DROP_CAST,
|
||||
COHERENCE_LEAK_CHECK,
|
||||
CONFLICTING_REPR_HINTS,
|
||||
CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
|
||||
CONST_EVALUATABLE_UNCHECKED,
|
||||
CONST_ITEM_MUTATION,
|
||||
DEAD_CODE,
|
||||
@ -2804,51 +2803,6 @@ declare_lint! {
|
||||
@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! {
|
||||
/// The `const_evaluatable_unchecked` lint detects a generic constant used
|
||||
/// in a type.
|
||||
|
@ -80,14 +80,23 @@ pub trait Provenance: Copy + fmt::Debug + 'static {
|
||||
}
|
||||
|
||||
/// 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)]
|
||||
pub struct CtfeProvenance(NonZero<u64>);
|
||||
|
||||
impl From<AllocId> for CtfeProvenance {
|
||||
fn from(value: AllocId) -> Self {
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -103,12 +112,14 @@ impl fmt::Debug for CtfeProvenance {
|
||||
}
|
||||
|
||||
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 {
|
||||
/// Returns the `AllocId` of this provenance.
|
||||
#[inline(always)]
|
||||
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.
|
||||
@ -117,10 +128,38 @@ impl CtfeProvenance {
|
||||
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.
|
||||
#[inline]
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
fn encode(&self, e: &mut E) {
|
||||
self.alloc_id().encode(e);
|
||||
self.immutable().encode(e);
|
||||
self.into_parts().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 {
|
||||
fn decode(decoder: &mut D) -> Self {
|
||||
let alloc_id: AllocId = Decodable::decode(decoder);
|
||||
let prov = CtfeProvenance::from(alloc_id);
|
||||
let immutable: bool = Decodable::decode(decoder);
|
||||
if immutable { prov.as_immutable() } else { prov }
|
||||
let parts = Decodable::decode(decoder);
|
||||
CtfeProvenance::from_parts(parts)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||
self.alloc_id().hash_stable(hcx, hasher);
|
||||
self.immutable().hash_stable(hcx, hasher);
|
||||
self.into_parts().hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
|
11
tests/crashes/const_mut_ref_check_bypass.rs
Normal file
11
tests/crashes/const_mut_ref_check_bypass.rs
Normal 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() {}
|
@ -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(const_heap)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![deny(const_eval_mutable_ptr_in_final_value)]
|
||||
use std::intrinsics;
|
||||
|
||||
const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 };
|
||||
//~^ error: mutable pointer in final value of constant
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,31 +1,8 @@
|
||||
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 };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -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() {
|
||||
}
|
@ -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
|
||||
|
@ -3,7 +3,6 @@
|
||||
//@ normalize-stderr-test: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
|
||||
|
||||
#![allow(static_mut_refs)]
|
||||
#![deny(const_eval_mutable_ptr_in_final_value)]
|
||||
use std::cell::UnsafeCell;
|
||||
use std::sync::atomic::*;
|
||||
|
||||
@ -18,13 +17,11 @@ static OH_YES: &mut i32 = &mut 42;
|
||||
//~| pointing to read-only memory
|
||||
static BAR: &mut () = &mut ();
|
||||
//~^ ERROR encountered mutable pointer in final value of static
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
|
||||
struct Foo<T>(T);
|
||||
|
||||
static BOO: &mut Foo<()> = &mut Foo(());
|
||||
//~^ ERROR encountered mutable pointer in final value of static
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
|
||||
const BLUNT: &mut i32 = &mut 42;
|
||||
//~^ 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 _;
|
||||
//~^ 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 _;
|
||||
//~^ 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 _;
|
||||
//~^ ERROR: mutable pointer in final value
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
|
||||
struct SyncPtr<T> {
|
||||
x: *const T,
|
||||
}
|
||||
unsafe impl<T> Sync for SyncPtr<T> {}
|
||||
|
||||
// These pass the lifetime checks because of the "tail expression" / "outer scope" rule.
|
||||
// (This relies on `SyncPtr` being a curly brace struct.)
|
||||
// However, we intern the inner memory as read-only, so this must be rejected.
|
||||
// These pass the lifetime checks because of the "tail expression" / "outer scope" rule. (This
|
||||
// relies on `SyncPtr` being a curly brace struct.) However, we intern the inner memory as
|
||||
// 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`.)
|
||||
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 _ };
|
||||
//~^ ERROR mutable pointer in final value
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
|
||||
const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
||||
//~^ ERROR mutable pointer in final value
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
|
||||
|
||||
fn main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
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;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $DIR/mutable_references.rs:16:1
|
||||
--> $DIR/mutable_references.rs:15:1
|
||||
|
|
||||
LL | static OH_YES: &mut i32 = &mut 42;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $DIR/mutable_references.rs:19:1
|
||||
--> $DIR/mutable_references.rs:18: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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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(());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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
|
||||
--> $DIR/mutable_references.rs:29:1
|
||||
--> $DIR/mutable_references.rs:26:1
|
||||
|
|
||||
LL | const BLUNT: &mut i32 = &mut 42;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $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 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $DIR/mutable_references.rs:43:1
|
||||
--> $DIR/mutable_references.rs:40:1
|
||||
|
|
||||
LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
|
||||
| ^^^^^^^^^^^^^^^ 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
|
||||
--> $DIR/mutable_references.rs:49:1
|
||||
--> $DIR/mutable_references.rs:46:1
|
||||
|
|
||||
LL | const MUH: Meh = Meh {
|
||||
| ^^^^^^^^^^^^^^ 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
|
||||
--> $DIR/mutable_references.rs:61:1
|
||||
--> $DIR/mutable_references.rs:58:1
|
||||
|
|
||||
LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $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 _) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $DIR/mutable_references.rs:75:1
|
||||
--> $DIR/mutable_references.rs:72:1
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $DIR/mutable_references.rs:78:43
|
||||
--> $DIR/mutable_references.rs:75:43
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
|
||||
| ^^^^^^^^^^^^^ constant accesses mutable global memory
|
||||
|
||||
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 _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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:86:1
|
||||
--> $DIR/mutable_references.rs:82: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>
|
||||
|
||||
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>
|
||||
|
||||
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
|
||||
--> $DIR/mutable_references.rs:102: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>
|
||||
|
||||
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 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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
|
||||
--> $DIR/mutable_references.rs:120:5
|
||||
--> $DIR/mutable_references.rs:113:5
|
||||
|
|
||||
LL | *OH_YES = 99;
|
||||
| ^^^^^^^^^^^^ cannot assign
|
||||
@ -189,227 +148,107 @@ LL | *OH_YES = 99;
|
||||
warning: skipping const checks
|
||||
|
|
||||
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;
|
||||
| ^^^^^^^
|
||||
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;
|
||||
| ^^^^^^^
|
||||
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 ();
|
||||
| ^^^^^^^
|
||||
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(());
|
||||
| ^^^^^^^^^^^^
|
||||
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;
|
||||
| ^^^^^^^
|
||||
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 };
|
||||
| ^^^^^^
|
||||
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 };
|
||||
| ^^^^^^^^^^^
|
||||
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) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
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),
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
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) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
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 _) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
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 _) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
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 };
|
||||
| ^^^^^^^
|
||||
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 };
|
||||
| ^^^^^^^^^^^
|
||||
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 _;
|
||||
| ^^^^^^^
|
||||
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 _;
|
||||
| ^^^^^^^
|
||||
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 _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
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) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
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 _ };
|
||||
| ^^^^^^^
|
||||
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 };
|
||||
| ^^^^^^
|
||||
|
||||
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.
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
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);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $DIR/static-no-inner-mut.rs:12:1
|
||||
--> $DIR/static-no-inner-mut.rs:11:1
|
||||
|
|
||||
LL | static REFMUT: &mut i32 = &mut 0;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $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}};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $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}};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $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 _ };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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
|
||||
--> $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 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
||||
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);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
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;
|
||||
| ^^^^^^
|
||||
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}};
|
||||
| ^^^^
|
||||
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}};
|
||||
| ^^^^^^^^
|
||||
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) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
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 _ };
|
||||
| ^^^^^^^
|
||||
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 };
|
||||
| ^^^^^^
|
||||
|
||||
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`.
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
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);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $DIR/static-no-inner-mut.rs:12:1
|
||||
--> $DIR/static-no-inner-mut.rs:11:1
|
||||
|
|
||||
LL | static REFMUT: &mut i32 = &mut 0;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $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}};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $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}};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
--> $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 _ };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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
|
||||
--> $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 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
||||
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);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
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;
|
||||
| ^^^^^^
|
||||
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}};
|
||||
| ^^^^
|
||||
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}};
|
||||
| ^^^^^^^^
|
||||
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) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
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 _ };
|
||||
| ^^^^^^^
|
||||
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 };
|
||||
| ^^^^^^
|
||||
|
||||
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`.
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
#![feature(const_refs_to_cell, const_mut_refs)]
|
||||
// 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.
|
||||
#![deny(const_eval_mutable_ptr_in_final_value)]
|
||||
use std::sync::atomic::*;
|
||||
|
||||
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.
|
||||
// (This relies on `SyncPtr` being a curly brace struct.)
|
||||
// Then they get interned immutably, which is not great.
|
||||
// `mut_ref_in_final.rs` and `std/cell.rs` ensure that we don't accept this even with the feature
|
||||
// fate, but for unleashed Miri there's not really any way we can reject them: it's just
|
||||
// non-dangling raw pointers.
|
||||
// Then they get interned immutably, which is not great. See
|
||||
// <https://github.com/rust-lang/rust/pull/128543> for why we accept such code.
|
||||
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 _ };
|
||||
//~^ ERROR mutable pointer in final value
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
|
||||
static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
||||
//~^ ERROR mutable pointer in final value
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
|
||||
fn main() {}
|
||||
|
@ -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
|
||||
// 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
|
||||
// is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) so for now we
|
||||
// reject this, though not with a great error message.
|
||||
// is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) but we've
|
||||
// done it since Rust 1.0 so we can't stop now.
|
||||
pub enum JsValue {
|
||||
Undefined,
|
||||
Object(Cell<bool>),
|
||||
@ -28,10 +28,8 @@ impl Drop for JsValue {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
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;
|
||||
// Making it clear that this is promotion, not "outer scope".
|
||||
const NONE_EXPLICIT_PROMOTED: &'static Option<Cell<i32>> = {
|
||||
|
@ -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) };
|
||||
| ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value
|
||||
|
||||
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
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user