validation: descend from consts into statics
This commit is contained in:
parent
4e77e368eb
commit
9c0623fe8f
@ -215,9 +215,6 @@ const_eval_modified_global =
|
|||||||
const_eval_mut_deref =
|
const_eval_mut_deref =
|
||||||
mutation through a reference is not allowed in {const_eval_const_context}s
|
mutation through a reference is not allowed in {const_eval_const_context}s
|
||||||
|
|
||||||
const_eval_mutable_data_in_const =
|
|
||||||
constant refers to mutable data
|
|
||||||
|
|
||||||
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
|
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
|
||||||
|
|
||||||
const_eval_non_const_fmt_macro_call =
|
const_eval_non_const_fmt_macro_call =
|
||||||
@ -414,6 +411,9 @@ const_eval_upcast_mismatch =
|
|||||||
## (We'd love to sort this differently to make that more clear but tidy won't let us...)
|
## (We'd love to sort this differently to make that more clear but tidy won't let us...)
|
||||||
const_eval_validation_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
|
const_eval_validation_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
|
||||||
const_eval_validation_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty}
|
const_eval_validation_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty}
|
||||||
|
|
||||||
|
const_eval_validation_const_ref_to_mutable = {$front_matter}: encountered reference to mutable memory in `const`
|
||||||
|
|
||||||
const_eval_validation_dangling_box_no_provenance = {$front_matter}: encountered a dangling box ({$pointer} has no provenance)
|
const_eval_validation_dangling_box_no_provenance = {$front_matter}: encountered a dangling box ({$pointer} has no provenance)
|
||||||
const_eval_validation_dangling_box_out_of_bounds = {$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)
|
const_eval_validation_dangling_box_out_of_bounds = {$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)
|
||||||
const_eval_validation_dangling_box_use_after_free = {$front_matter}: encountered a dangling box (use-after-free)
|
const_eval_validation_dangling_box_use_after_free = {$front_matter}: encountered a dangling box (use-after-free)
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
// Not in interpret to make sure we do not use private implementation details
|
// Not in interpret to make sure we do not use private implementation details
|
||||||
|
|
||||||
use crate::interpret::InterpCx;
|
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::{InterpError, InterpErrorInfo};
|
use rustc_middle::mir::interpret::InterpErrorInfo;
|
||||||
use rustc_middle::query::TyCtxtAt;
|
use rustc_middle::query::TyCtxtAt;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
|
|
||||||
|
use crate::interpret::{format_interp_error, InterpCx};
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod eval_queries;
|
mod eval_queries;
|
||||||
mod fn_queries;
|
mod fn_queries;
|
||||||
@ -25,24 +26,17 @@ pub(crate) enum ValTreeCreationError {
|
|||||||
NodesOverflow,
|
NodesOverflow,
|
||||||
/// Values of this type, or this particular value, are not supported as valtrees.
|
/// Values of this type, or this particular value, are not supported as valtrees.
|
||||||
NonSupportedType,
|
NonSupportedType,
|
||||||
/// The value pointed to non-read-only memory, so we cannot make it a valtree.
|
|
||||||
NotReadOnly,
|
|
||||||
Other,
|
|
||||||
}
|
}
|
||||||
pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>;
|
pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>;
|
||||||
|
|
||||||
impl From<InterpErrorInfo<'_>> for ValTreeCreationError {
|
impl From<InterpErrorInfo<'_>> for ValTreeCreationError {
|
||||||
fn from(err: InterpErrorInfo<'_>) -> Self {
|
fn from(err: InterpErrorInfo<'_>) -> Self {
|
||||||
match err.kind() {
|
ty::tls::with(|tcx| {
|
||||||
InterpError::MachineStop(err) => {
|
bug!(
|
||||||
let err = err.downcast_ref::<ConstEvalErrKind>().unwrap();
|
"Unexpected Undefined Behavior error during valtree construction: {}",
|
||||||
match err {
|
format_interp_error(tcx.dcx(), err),
|
||||||
ConstEvalErrKind::ConstAccessesMutGlobal => ValTreeCreationError::NotReadOnly,
|
)
|
||||||
_ => ValTreeCreationError::Other,
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => ValTreeCreationError::Other,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
use super::machine::CompileTimeEvalContext;
|
use super::machine::CompileTimeEvalContext;
|
||||||
use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
|
use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
|
||||||
use crate::const_eval::CanAccessMutGlobal;
|
use crate::const_eval::CanAccessMutGlobal;
|
||||||
use crate::errors::{MaxNumNodesInConstErr, MutableDataInConstErr};
|
use crate::errors::MaxNumNodesInConstErr;
|
||||||
use crate::interpret::MPlaceTy;
|
use crate::interpret::MPlaceTy;
|
||||||
use crate::interpret::{
|
use crate::interpret::{
|
||||||
intern_const_alloc_recursive, ImmTy, Immediate, InternKind, MemPlaceMeta, MemoryKind, PlaceTy,
|
intern_const_alloc_recursive, ImmTy, Immediate, InternKind, MemPlaceMeta, MemoryKind, PlaceTy,
|
||||||
@ -249,18 +249,6 @@ pub(crate) fn eval_to_valtree<'tcx>(
|
|||||||
tcx.dcx().emit_err(MaxNumNodesInConstErr { span, global_const_id });
|
tcx.dcx().emit_err(MaxNumNodesInConstErr { span, global_const_id });
|
||||||
Err(handled.into())
|
Err(handled.into())
|
||||||
}
|
}
|
||||||
ValTreeCreationError::NotReadOnly => {
|
|
||||||
let handled =
|
|
||||||
tcx.dcx().emit_err(MutableDataInConstErr { span, global_const_id });
|
|
||||||
Err(handled.into())
|
|
||||||
}
|
|
||||||
ValTreeCreationError::Other => {
|
|
||||||
let handled = tcx.dcx().span_delayed_bug(
|
|
||||||
span.unwrap_or(DUMMY_SP),
|
|
||||||
"unexpected error during valtree construction",
|
|
||||||
);
|
|
||||||
Err(handled.into())
|
|
||||||
}
|
|
||||||
ValTreeCreationError::NonSupportedType => Ok(None),
|
ValTreeCreationError::NonSupportedType => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,14 +117,6 @@ pub(crate) struct MaxNumNodesInConstErr {
|
|||||||
pub global_const_id: String,
|
pub global_const_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(const_eval_mutable_data_in_const)]
|
|
||||||
pub(crate) struct MutableDataInConstErr {
|
|
||||||
#[primary_span]
|
|
||||||
pub span: Option<Span>,
|
|
||||||
pub global_const_id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(const_eval_unallowed_fn_pointer_call)]
|
#[diag(const_eval_unallowed_fn_pointer_call)]
|
||||||
pub(crate) struct UnallowedFnPointerCall {
|
pub(crate) struct UnallowedFnPointerCall {
|
||||||
@ -619,6 +611,7 @@ fn diagnostic_message(&self) -> DiagnosticMessage {
|
|||||||
|
|
||||||
PointerAsInt { .. } => const_eval_validation_pointer_as_int,
|
PointerAsInt { .. } => const_eval_validation_pointer_as_int,
|
||||||
PartialPointer => const_eval_validation_partial_pointer,
|
PartialPointer => const_eval_validation_partial_pointer,
|
||||||
|
ConstRefToMutable => const_eval_validation_const_ref_to_mutable,
|
||||||
MutableRefInConst => const_eval_validation_mutable_ref_in_const,
|
MutableRefInConst => const_eval_validation_mutable_ref_in_const,
|
||||||
MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable,
|
MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable,
|
||||||
NullFnPtr => const_eval_validation_null_fn_ptr,
|
NullFnPtr => const_eval_validation_null_fn_ptr,
|
||||||
@ -773,6 +766,7 @@ fn add_range_arg<G: EmissionGuarantee>(
|
|||||||
NullPtr { .. }
|
NullPtr { .. }
|
||||||
| PtrToStatic { .. }
|
| PtrToStatic { .. }
|
||||||
| MutableRefInConst
|
| MutableRefInConst
|
||||||
|
| ConstRefToMutable
|
||||||
| MutableRefToImmutable
|
| MutableRefToImmutable
|
||||||
| NullFnPtr
|
| NullFnPtr
|
||||||
| NeverVal
|
| NeverVal
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
use either::{Either, Left, Right};
|
use either::{Either, Left, Right};
|
||||||
|
|
||||||
use hir::CRATE_HIR_ID;
|
use hir::CRATE_HIR_ID;
|
||||||
|
use rustc_errors::DiagCtxt;
|
||||||
use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
|
use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
@ -430,6 +431,26 @@ pub(super) fn from_known_layout<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Turn the given error into a human-readable string. Expects the string to be printed, so if
|
||||||
|
/// `RUSTC_CTFE_BACKTRACE` is set this will show a backtrace of the rustc internals that
|
||||||
|
/// triggered the error.
|
||||||
|
///
|
||||||
|
/// This is NOT the preferred way to render an error; use `report` from `const_eval` instead.
|
||||||
|
/// However, this is useful when error messages appear in ICEs.
|
||||||
|
pub fn format_interp_error<'tcx>(dcx: &DiagCtxt, e: InterpErrorInfo<'tcx>) -> String {
|
||||||
|
let (e, backtrace) = e.into_parts();
|
||||||
|
backtrace.print_backtrace();
|
||||||
|
// FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the
|
||||||
|
// label and arguments from the InterpError.
|
||||||
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
|
let mut diag = dcx.struct_allow("");
|
||||||
|
let msg = e.diagnostic_message();
|
||||||
|
e.add_args(dcx, &mut diag);
|
||||||
|
let s = dcx.eagerly_translate_to_string(msg, diag.args());
|
||||||
|
diag.cancel();
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
@ -462,27 +483,6 @@ pub fn best_lint_scope(&self) -> hir::HirId {
|
|||||||
.map_or(CRATE_HIR_ID, |def_id| self.tcx.local_def_id_to_hir_id(def_id))
|
.map_or(CRATE_HIR_ID, |def_id| self.tcx.local_def_id_to_hir_id(def_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turn the given error into a human-readable string. Expects the string to be printed, so if
|
|
||||||
/// `RUSTC_CTFE_BACKTRACE` is set this will show a backtrace of the rustc internals that
|
|
||||||
/// triggered the error.
|
|
||||||
///
|
|
||||||
/// This is NOT the preferred way to render an error; use `report` from `const_eval` instead.
|
|
||||||
/// However, this is useful when error messages appear in ICEs.
|
|
||||||
pub fn format_error(&self, e: InterpErrorInfo<'tcx>) -> String {
|
|
||||||
let (e, backtrace) = e.into_parts();
|
|
||||||
backtrace.print_backtrace();
|
|
||||||
// FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the
|
|
||||||
// label and arguments from the InterpError.
|
|
||||||
let dcx = self.tcx.dcx();
|
|
||||||
#[allow(rustc::untranslatable_diagnostic)]
|
|
||||||
let mut diag = dcx.struct_allow("");
|
|
||||||
let msg = e.diagnostic_message();
|
|
||||||
e.add_args(dcx, &mut diag);
|
|
||||||
let s = dcx.eagerly_translate_to_string(msg, diag.args());
|
|
||||||
diag.cancel();
|
|
||||||
s
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn stack(&self) -> &[Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>] {
|
pub(crate) fn stack(&self) -> &[Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>] {
|
||||||
M::stack(self)
|
M::stack(self)
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here
|
pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here
|
||||||
|
|
||||||
pub use self::eval_context::{Frame, FrameInfo, InterpCx, StackPopCleanup};
|
pub use self::eval_context::{format_interp_error, Frame, FrameInfo, InterpCx, StackPopCleanup};
|
||||||
pub use self::intern::{
|
pub use self::intern::{
|
||||||
intern_const_alloc_for_constprop, intern_const_alloc_recursive, InternKind,
|
intern_const_alloc_for_constprop, intern_const_alloc_recursive, InternKind,
|
||||||
};
|
};
|
||||||
|
@ -27,8 +27,9 @@
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AllocId, CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy,
|
format_interp_error, AllocId, CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx,
|
||||||
Machine, MemPlaceMeta, OpTy, Pointer, Projectable, Scalar, ValueVisitor,
|
InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Pointer, Projectable, Scalar,
|
||||||
|
ValueVisitor,
|
||||||
};
|
};
|
||||||
|
|
||||||
// for the validation errors
|
// for the validation errors
|
||||||
@ -460,22 +461,23 @@ fn check_safe_pointer(
|
|||||||
// Special handling for pointers to statics (irrespective of their type).
|
// Special handling for pointers to statics (irrespective of their type).
|
||||||
assert!(!self.ecx.tcx.is_thread_local_static(did));
|
assert!(!self.ecx.tcx.is_thread_local_static(did));
|
||||||
assert!(self.ecx.tcx.is_static(did));
|
assert!(self.ecx.tcx.is_static(did));
|
||||||
// Mutability check.
|
let is_mut =
|
||||||
if ptr_expected_mutbl == Mutability::Mut {
|
matches!(self.ecx.tcx.def_kind(did), DefKind::Static(Mutability::Mut))
|
||||||
if matches!(
|
|| !self
|
||||||
self.ecx.tcx.def_kind(did),
|
|
||||||
DefKind::Static(Mutability::Not)
|
|
||||||
) && self
|
|
||||||
.ecx
|
.ecx
|
||||||
.tcx
|
.tcx
|
||||||
.type_of(did)
|
.type_of(did)
|
||||||
.no_bound_vars()
|
.no_bound_vars()
|
||||||
.expect("statics should not have generic parameters")
|
.expect("statics should not have generic parameters")
|
||||||
.is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all())
|
.is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all());
|
||||||
{
|
// Mutability check.
|
||||||
|
if ptr_expected_mutbl == Mutability::Mut {
|
||||||
|
if !is_mut {
|
||||||
throw_validation_failure!(self.path, MutableRefToImmutable);
|
throw_validation_failure!(self.path, MutableRefToImmutable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
match self.ctfe_mode {
|
||||||
|
Some(CtfeValidationMode::Static { .. }) => {
|
||||||
// We skip recursively checking other statics. These statics must be sound by
|
// We skip recursively checking other statics. These statics must be sound by
|
||||||
// themselves, and the only way to get broken statics here is by using
|
// themselves, and the only way to get broken statics here is by using
|
||||||
// unsafe code.
|
// unsafe code.
|
||||||
@ -483,23 +485,25 @@ fn check_safe_pointer(
|
|||||||
// sound cases, the static was already validated on its own, and second, we
|
// sound cases, the static was already validated on its own, and second, we
|
||||||
// trigger cycle errors if we try to compute the value of the other static
|
// trigger cycle errors if we try to compute the value of the other static
|
||||||
// and that static refers back to us.
|
// and that static refers back to us.
|
||||||
// We might miss const-invalid data,
|
// This could miss some UB, but that's fine.
|
||||||
// but things are still sound otherwise (in particular re: consts
|
|
||||||
// referring to statics).
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
Some(CtfeValidationMode::Const { .. }) => {
|
||||||
|
// For consts on the other hand we have to recursively check;
|
||||||
|
// pattern matching assumes a valid value. However we better make
|
||||||
|
// sure this is not mutable.
|
||||||
|
if is_mut {
|
||||||
|
throw_validation_failure!(self.path, ConstRefToMutable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
GlobalAlloc::Memory(alloc) => {
|
GlobalAlloc::Memory(alloc) => {
|
||||||
if alloc.inner().mutability == Mutability::Mut
|
if alloc.inner().mutability == Mutability::Mut
|
||||||
&& matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
|
&& matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
|
||||||
{
|
{
|
||||||
// This is impossible: this can only be some inner allocation of a
|
throw_validation_failure!(self.path, ConstRefToMutable);
|
||||||
// `static mut` (everything else either hits the `GlobalAlloc::Static`
|
|
||||||
// case or is interned immutably). To get such a pointer we'd have to
|
|
||||||
// load it from a static, but such loads lead to a CTFE error.
|
|
||||||
span_bug!(
|
|
||||||
self.ecx.tcx.span,
|
|
||||||
"encountered reference to mutable memory inside a `const`"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if ptr_expected_mutbl == Mutability::Mut
|
if ptr_expected_mutbl == Mutability::Mut
|
||||||
&& alloc.inner().mutability == Mutability::Not
|
&& alloc.inner().mutability == Mutability::Not
|
||||||
@ -978,7 +982,10 @@ fn validate_operand_internal(
|
|||||||
// Complain about any other kind of error -- those are bad because we'd like to
|
// Complain about any other kind of error -- those are bad because we'd like to
|
||||||
// report them in a way that shows *where* in the value the issue lies.
|
// report them in a way that shows *where* in the value the issue lies.
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
bug!("Unexpected error during validation: {}", self.format_error(err));
|
bug!(
|
||||||
|
"Unexpected error during validation: {}",
|
||||||
|
format_interp_error(self.tcx.dcx(), err)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -417,6 +417,7 @@ pub enum ValidationErrorKind<'tcx> {
|
|||||||
PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
|
PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
|
||||||
PtrToStatic { ptr_kind: PointerKind },
|
PtrToStatic { ptr_kind: PointerKind },
|
||||||
MutableRefInConst,
|
MutableRefInConst,
|
||||||
|
ConstRefToMutable,
|
||||||
MutableRefToImmutable,
|
MutableRefToImmutable,
|
||||||
UnsafeCellInImmutable,
|
UnsafeCellInImmutable,
|
||||||
NullFnPtr,
|
NullFnPtr,
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use rustc_const_eval::interpret::{ImmTy, Projectable};
|
use rustc_const_eval::interpret::{
|
||||||
use rustc_const_eval::interpret::{InterpCx, InterpResult, Scalar};
|
format_interp_error, ImmTy, InterpCx, InterpResult, Projectable, Scalar,
|
||||||
|
};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
@ -246,7 +247,7 @@ fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
|
|||||||
assert!(
|
assert!(
|
||||||
!error.kind().formatted_string(),
|
!error.kind().formatted_string(),
|
||||||
"const-prop encountered formatting error: {}",
|
"const-prop encountered formatting error: {}",
|
||||||
self.ecx.format_error(error),
|
format_interp_error(self.ecx.tcx.dcx(), error),
|
||||||
);
|
);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -290,7 +290,7 @@ pub fn report_error<'tcx, 'mir>(
|
|||||||
) =>
|
) =>
|
||||||
{
|
{
|
||||||
ecx.handle_ice(); // print interpreter backtrace
|
ecx.handle_ice(); // print interpreter backtrace
|
||||||
bug!("This validation error should be impossible in Miri: {}", ecx.format_error(e));
|
bug!("This validation error should be impossible in Miri: {}", format_interp_error(ecx.tcx.dcx(), e));
|
||||||
}
|
}
|
||||||
UndefinedBehavior(_) => "Undefined Behavior",
|
UndefinedBehavior(_) => "Undefined Behavior",
|
||||||
ResourceExhaustion(_) => "resource exhaustion",
|
ResourceExhaustion(_) => "resource exhaustion",
|
||||||
@ -304,7 +304,7 @@ pub fn report_error<'tcx, 'mir>(
|
|||||||
) => "post-monomorphization error",
|
) => "post-monomorphization error",
|
||||||
_ => {
|
_ => {
|
||||||
ecx.handle_ice(); // print interpreter backtrace
|
ecx.handle_ice(); // print interpreter backtrace
|
||||||
bug!("This error should be impossible in Miri: {}", ecx.format_error(e));
|
bug!("This error should be impossible in Miri: {}", format_interp_error(ecx.tcx.dcx(), e));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
@ -370,7 +370,7 @@ pub fn report_error<'tcx, 'mir>(
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.insert(0, ecx.format_error(e));
|
msg.insert(0, format_interp_error(ecx.tcx.dcx(), e));
|
||||||
|
|
||||||
report_msg(
|
report_msg(
|
||||||
DiagLevel::Error,
|
DiagLevel::Error,
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
|
// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
|
||||||
|
// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
|
||||||
#![feature(const_refs_to_static, const_mut_refs, sync_unsafe_cell)]
|
#![feature(const_refs_to_static, const_mut_refs, sync_unsafe_cell)]
|
||||||
use std::cell::SyncUnsafeCell;
|
use std::cell::SyncUnsafeCell;
|
||||||
|
|
||||||
static S: SyncUnsafeCell<i32> = SyncUnsafeCell::new(0);
|
static S: SyncUnsafeCell<i32> = SyncUnsafeCell::new(0);
|
||||||
static mut S_MUT: i32 = 0;
|
static mut S_MUT: i32 = 0;
|
||||||
|
|
||||||
const C1: &SyncUnsafeCell<i32> = &S;
|
const C1: &SyncUnsafeCell<i32> = &S; //~ERROR undefined behavior
|
||||||
|
//~| encountered reference to mutable memory
|
||||||
const C1_READ: () = unsafe {
|
const C1_READ: () = unsafe {
|
||||||
assert!(*C1.get() == 0); //~ERROR evaluation of constant value failed
|
assert!(*C1.get() == 0);
|
||||||
//~^ constant accesses mutable global memory
|
|
||||||
};
|
};
|
||||||
const C2: *const i32 = unsafe { std::ptr::addr_of!(S_MUT) };
|
const C2: *const i32 = unsafe { std::ptr::addr_of!(S_MUT) };
|
||||||
const C2_READ: () = unsafe {
|
const C2_READ: () = unsafe {
|
||||||
|
@ -1,11 +1,22 @@
|
|||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const_refs_to_static_fail.rs:9:13
|
--> $DIR/const_refs_to_static_fail.rs:9:1
|
||||||
|
|
|
||||||
|
LL | const C1: &SyncUnsafeCell<i32> = &S;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||||
|
HEX_DUMP
|
||||||
|
}
|
||||||
|
|
||||||
|
note: erroneous constant encountered
|
||||||
|
--> $DIR/const_refs_to_static_fail.rs:12:14
|
||||||
|
|
|
|
||||||
LL | assert!(*C1.get() == 0);
|
LL | assert!(*C1.get() == 0);
|
||||||
| ^^^^^^^^^ constant accesses mutable global memory
|
| ^^
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/const_refs_to_static_fail.rs:14:13
|
--> $DIR/const_refs_to_static_fail.rs:16:13
|
||||||
|
|
|
|
||||||
LL | assert!(*C2 == 0);
|
LL | assert!(*C2 == 0);
|
||||||
| ^^^ constant accesses mutable global memory
|
| ^^^ constant accesses mutable global memory
|
||||||
|
17
tests/ui/consts/const_refs_to_static_fail_invalid.rs
Normal file
17
tests/ui/consts/const_refs_to_static_fail_invalid.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
|
||||||
|
// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
|
||||||
|
#![feature(const_refs_to_static)]
|
||||||
|
|
||||||
|
static S: i8 = 10;
|
||||||
|
|
||||||
|
const C: &bool = unsafe { std::mem::transmute(&S) };
|
||||||
|
//~^ERROR: undefined behavior
|
||||||
|
//~| expected a boolean
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// This must be rejected here (or earlier), since it's not a valid `&bool`.
|
||||||
|
match &true {
|
||||||
|
C => {}, //~ERROR: could not evaluate constant pattern
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
20
tests/ui/consts/const_refs_to_static_fail_invalid.stderr
Normal file
20
tests/ui/consts/const_refs_to_static_fail_invalid.stderr
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
error[E0080]: it is undefined behavior to use this value
|
||||||
|
--> $DIR/const_refs_to_static_fail_invalid.rs:7:1
|
||||||
|
|
|
||||||
|
LL | const C: &bool = unsafe { std::mem::transmute(&S) };
|
||||||
|
| ^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered 0x0a, but expected a boolean
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||||
|
HEX_DUMP
|
||||||
|
}
|
||||||
|
|
||||||
|
error: could not evaluate constant pattern
|
||||||
|
--> $DIR/const_refs_to_static_fail_invalid.rs:14:9
|
||||||
|
|
|
||||||
|
LL | C => {},
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0080`.
|
@ -1,9 +1,12 @@
|
|||||||
|
// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
|
||||||
|
// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
|
||||||
#![feature(const_refs_to_static)]
|
#![feature(const_refs_to_static)]
|
||||||
|
|
||||||
static mut S_MUT: i32 = 0;
|
static mut S_MUT: i32 = 0;
|
||||||
|
|
||||||
const C: &i32 = unsafe { &S_MUT };
|
const C: &i32 = unsafe { &S_MUT };
|
||||||
//~^ERROR: constant refers to mutable data
|
//~^ERROR: undefined behavior
|
||||||
|
//~| encountered reference to mutable memory
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// This *must not build*, the constant we are matching against
|
// This *must not build*, the constant we are matching against
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
error: constant refers to mutable data
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const_refs_to_static_fail_pattern.rs:5:1
|
--> $DIR/const_refs_to_static_fail_pattern.rs:7:1
|
||||||
|
|
|
|
||||||
LL | const C: &i32 = unsafe { &S_MUT };
|
LL | const C: &i32 = unsafe { &S_MUT };
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||||
|
HEX_DUMP
|
||||||
|
}
|
||||||
|
|
||||||
error: could not evaluate constant pattern
|
error: could not evaluate constant pattern
|
||||||
--> $DIR/const_refs_to_static_fail_pattern.rs:12:9
|
--> $DIR/const_refs_to_static_fail_pattern.rs:15:9
|
||||||
|
|
|
|
||||||
LL | C => {},
|
LL | C => {},
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0080`.
|
||||||
|
@ -16,6 +16,17 @@ error[E0080]: evaluation of constant value failed
|
|||||||
LL | const READ_MUT: u32 = unsafe { MUTABLE };
|
LL | const READ_MUT: u32 = unsafe { MUTABLE };
|
||||||
| ^^^^^^^ constant accesses mutable global memory
|
| ^^^^^^^ constant accesses mutable global memory
|
||||||
|
|
||||||
|
error[E0080]: it is undefined behavior to use this value
|
||||||
|
--> $DIR/const_refers_to_static.rs:21:1
|
||||||
|
|
|
||||||
|
LL | const REF_INTERIOR_MUT: &usize = {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: 4, align: 4) {
|
||||||
|
╾ALLOC0<imm>╼ │ ╾──╼
|
||||||
|
}
|
||||||
|
|
||||||
warning: skipping const checks
|
warning: skipping const checks
|
||||||
|
|
|
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
@ -44,16 +55,16 @@ help: skipping check for `const_refs_to_static` feature
|
|||||||
LL | const READ_MUT: u32 = unsafe { MUTABLE };
|
LL | const READ_MUT: u32 = unsafe { MUTABLE };
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static.rs:23:18
|
--> $DIR/const_refers_to_static.rs:24:18
|
||||||
|
|
|
|
||||||
LL | unsafe { &*(&FOO as *const _ as *const usize) }
|
LL | unsafe { &*(&FOO as *const _ as *const usize) }
|
||||||
| ^^^
|
| ^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static.rs:27:25
|
--> $DIR/const_refers_to_static.rs:29:25
|
||||||
|
|
|
|
||||||
LL | const REF_IMMUT: &u8 = &MY_STATIC;
|
LL | const REF_IMMUT: &u8 = &MY_STATIC;
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors; 1 warning emitted
|
error: aborting due to 4 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`.
|
||||||
|
@ -16,6 +16,17 @@ error[E0080]: evaluation of constant value failed
|
|||||||
LL | const READ_MUT: u32 = unsafe { MUTABLE };
|
LL | const READ_MUT: u32 = unsafe { MUTABLE };
|
||||||
| ^^^^^^^ constant accesses mutable global memory
|
| ^^^^^^^ constant accesses mutable global memory
|
||||||
|
|
||||||
|
error[E0080]: it is undefined behavior to use this value
|
||||||
|
--> $DIR/const_refers_to_static.rs:21:1
|
||||||
|
|
|
||||||
|
LL | const REF_INTERIOR_MUT: &usize = {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: 8, align: 8) {
|
||||||
|
╾ALLOC0<imm>╼ │ ╾──────╼
|
||||||
|
}
|
||||||
|
|
||||||
warning: skipping const checks
|
warning: skipping const checks
|
||||||
|
|
|
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
@ -44,16 +55,16 @@ help: skipping check for `const_refs_to_static` feature
|
|||||||
LL | const READ_MUT: u32 = unsafe { MUTABLE };
|
LL | const READ_MUT: u32 = unsafe { MUTABLE };
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static.rs:23:18
|
--> $DIR/const_refers_to_static.rs:24:18
|
||||||
|
|
|
|
||||||
LL | unsafe { &*(&FOO as *const _ as *const usize) }
|
LL | unsafe { &*(&FOO as *const _ as *const usize) }
|
||||||
| ^^^
|
| ^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static.rs:27:25
|
--> $DIR/const_refers_to_static.rs:29:25
|
||||||
|
|
|
|
||||||
LL | const REF_IMMUT: &u8 = &MY_STATIC;
|
LL | const REF_IMMUT: &u8 = &MY_STATIC;
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors; 1 warning emitted
|
error: aborting due to 4 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`.
|
||||||
|
@ -17,12 +17,14 @@
|
|||||||
static mut MUTABLE: u32 = 0;
|
static mut MUTABLE: u32 = 0;
|
||||||
const READ_MUT: u32 = unsafe { MUTABLE }; //~ERROR evaluation of constant value failed
|
const READ_MUT: u32 = unsafe { MUTABLE }; //~ERROR evaluation of constant value failed
|
||||||
|
|
||||||
// Not actually reading from anything mutable, so these are fine.
|
// Evaluating this does not read anything mutable, but validation does, so this should error.
|
||||||
const REF_INTERIOR_MUT: &usize = {
|
const REF_INTERIOR_MUT: &usize = { //~ ERROR undefined behavior
|
||||||
|
//~| encountered reference to mutable memory
|
||||||
static FOO: AtomicUsize = AtomicUsize::new(0);
|
static FOO: AtomicUsize = AtomicUsize::new(0);
|
||||||
unsafe { &*(&FOO as *const _ as *const usize) }
|
unsafe { &*(&FOO as *const _ as *const usize) }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Not actually reading from anything mutable, so these are fine.
|
||||||
static MY_STATIC: u8 = 4;
|
static MY_STATIC: u8 = 4;
|
||||||
const REF_IMMUT: &u8 = &MY_STATIC;
|
const REF_IMMUT: &u8 = &MY_STATIC;
|
||||||
const READ_IMMUT: u8 = *REF_IMMUT;
|
const READ_IMMUT: u8 = *REF_IMMUT;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
warning: shared reference of mutable static is discouraged
|
warning: shared reference of mutable static is discouraged
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:11:14
|
--> $DIR/const_refers_to_static_cross_crate.rs:12:14
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO }
|
LL | unsafe { &static_cross_crate::ZERO }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ shared reference of mutable static
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ shared reference of mutable static
|
||||||
@ -13,50 +13,65 @@ help: shared references are dangerous since if there's any kind of mutation of t
|
|||||||
LL | unsafe { addr_of!(static_cross_crate::ZERO) }
|
LL | unsafe { addr_of!(static_cross_crate::ZERO) }
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: constant refers to mutable data
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:10:1
|
--> $DIR/const_refers_to_static_cross_crate.rs:10:1
|
||||||
|
|
|
|
||||||
LL | const SLICE_MUT: &[u8; 1] = {
|
LL | const SLICE_MUT: &[u8; 1] = {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: 4, align: 4) {
|
||||||
|
╾ALLOC0<imm>╼ │ ╾──╼
|
||||||
|
}
|
||||||
|
|
||||||
error: could not evaluate constant pattern
|
error: could not evaluate constant pattern
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:36:9
|
--> $DIR/const_refers_to_static_cross_crate.rs:39:9
|
||||||
|
|
|
|
||||||
LL | SLICE_MUT => true,
|
LL | SLICE_MUT => true,
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: constant refers to mutable data
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:15:1
|
--> $DIR/const_refers_to_static_cross_crate.rs:16:1
|
||||||
|
|
|
|
||||||
LL | const U8_MUT: &u8 = {
|
LL | const U8_MUT: &u8 = {
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: 4, align: 4) {
|
||||||
|
╾ALLOC0<imm>╼ │ ╾──╼
|
||||||
|
}
|
||||||
|
|
||||||
error: could not evaluate constant pattern
|
error: could not evaluate constant pattern
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:44:9
|
--> $DIR/const_refers_to_static_cross_crate.rs:47:9
|
||||||
|
|
|
|
||||||
LL | U8_MUT => true,
|
LL | U8_MUT => true,
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: constant refers to mutable data
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:20:1
|
--> $DIR/const_refers_to_static_cross_crate.rs:22:1
|
||||||
|
|
|
|
||||||
LL | const U8_MUT2: &u8 = {
|
LL | const U8_MUT2: &u8 = {
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: 4, align: 4) {
|
||||||
|
╾ALLOC0<imm>╼ │ ╾──╼
|
||||||
|
}
|
||||||
|
|
||||||
error: could not evaluate constant pattern
|
error: could not evaluate constant pattern
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:54:9
|
--> $DIR/const_refers_to_static_cross_crate.rs:57:9
|
||||||
|
|
|
|
||||||
LL | U8_MUT2 => true,
|
LL | U8_MUT2 => true,
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory
|
||||||
|
|
||||||
error: could not evaluate constant pattern
|
error: could not evaluate constant pattern
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:61:9
|
--> $DIR/const_refers_to_static_cross_crate.rs:64:9
|
||||||
|
|
|
|
||||||
LL | U8_MUT3 => true,
|
LL | U8_MUT3 => true,
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@ -64,57 +79,57 @@ LL | U8_MUT3 => true,
|
|||||||
warning: skipping const checks
|
warning: skipping const checks
|
||||||
|
|
|
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:11:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:12:15
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO }
|
LL | unsafe { &static_cross_crate::ZERO }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:11:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:12:15
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO }
|
LL | unsafe { &static_cross_crate::ZERO }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:16:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:18:15
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO[0] }
|
LL | unsafe { &static_cross_crate::ZERO[0] }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:16:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:18:15
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO[0] }
|
LL | unsafe { &static_cross_crate::ZERO[0] }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:16:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:18:15
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO[0] }
|
LL | unsafe { &static_cross_crate::ZERO[0] }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:21:17
|
--> $DIR/const_refers_to_static_cross_crate.rs:24:17
|
||||||
|
|
|
|
||||||
LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] }
|
LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
warning: shared reference of mutable static is discouraged
|
warning: shared reference of mutable static is discouraged
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:11:14
|
--> $DIR/const_refers_to_static_cross_crate.rs:12:14
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO }
|
LL | unsafe { &static_cross_crate::ZERO }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ shared reference of mutable static
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ shared reference of mutable static
|
||||||
@ -13,50 +13,65 @@ help: shared references are dangerous since if there's any kind of mutation of t
|
|||||||
LL | unsafe { addr_of!(static_cross_crate::ZERO) }
|
LL | unsafe { addr_of!(static_cross_crate::ZERO) }
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: constant refers to mutable data
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:10:1
|
--> $DIR/const_refers_to_static_cross_crate.rs:10:1
|
||||||
|
|
|
|
||||||
LL | const SLICE_MUT: &[u8; 1] = {
|
LL | const SLICE_MUT: &[u8; 1] = {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: 8, align: 8) {
|
||||||
|
╾ALLOC0<imm>╼ │ ╾──────╼
|
||||||
|
}
|
||||||
|
|
||||||
error: could not evaluate constant pattern
|
error: could not evaluate constant pattern
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:36:9
|
--> $DIR/const_refers_to_static_cross_crate.rs:39:9
|
||||||
|
|
|
|
||||||
LL | SLICE_MUT => true,
|
LL | SLICE_MUT => true,
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: constant refers to mutable data
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:15:1
|
--> $DIR/const_refers_to_static_cross_crate.rs:16:1
|
||||||
|
|
|
|
||||||
LL | const U8_MUT: &u8 = {
|
LL | const U8_MUT: &u8 = {
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: 8, align: 8) {
|
||||||
|
╾ALLOC0<imm>╼ │ ╾──────╼
|
||||||
|
}
|
||||||
|
|
||||||
error: could not evaluate constant pattern
|
error: could not evaluate constant pattern
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:44:9
|
--> $DIR/const_refers_to_static_cross_crate.rs:47:9
|
||||||
|
|
|
|
||||||
LL | U8_MUT => true,
|
LL | U8_MUT => true,
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: constant refers to mutable data
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:20:1
|
--> $DIR/const_refers_to_static_cross_crate.rs:22:1
|
||||||
|
|
|
|
||||||
LL | const U8_MUT2: &u8 = {
|
LL | const U8_MUT2: &u8 = {
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: 8, align: 8) {
|
||||||
|
╾ALLOC0<imm>╼ │ ╾──────╼
|
||||||
|
}
|
||||||
|
|
||||||
error: could not evaluate constant pattern
|
error: could not evaluate constant pattern
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:54:9
|
--> $DIR/const_refers_to_static_cross_crate.rs:57:9
|
||||||
|
|
|
|
||||||
LL | U8_MUT2 => true,
|
LL | U8_MUT2 => true,
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory
|
||||||
|
|
||||||
error: could not evaluate constant pattern
|
error: could not evaluate constant pattern
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:61:9
|
--> $DIR/const_refers_to_static_cross_crate.rs:64:9
|
||||||
|
|
|
|
||||||
LL | U8_MUT3 => true,
|
LL | U8_MUT3 => true,
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@ -64,57 +79,57 @@ LL | U8_MUT3 => true,
|
|||||||
warning: skipping const checks
|
warning: skipping const checks
|
||||||
|
|
|
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:11:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:12:15
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO }
|
LL | unsafe { &static_cross_crate::ZERO }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:11:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:12:15
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO }
|
LL | unsafe { &static_cross_crate::ZERO }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:16:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:18:15
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO[0] }
|
LL | unsafe { &static_cross_crate::ZERO[0] }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:16:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:18:15
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO[0] }
|
LL | unsafe { &static_cross_crate::ZERO[0] }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:16:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:18:15
|
||||||
|
|
|
|
||||||
LL | unsafe { &static_cross_crate::ZERO[0] }
|
LL | unsafe { &static_cross_crate::ZERO[0] }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:21:17
|
--> $DIR/const_refers_to_static_cross_crate.rs:24:17
|
||||||
|
|
|
|
||||||
LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] }
|
LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/const_refers_to_static_cross_crate.rs:25:15
|
--> $DIR/const_refers_to_static_cross_crate.rs:28:15
|
||||||
|
|
|
|
||||||
LL | match static_cross_crate::OPT_ZERO {
|
LL | match static_cross_crate::OPT_ZERO {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -7,17 +7,20 @@
|
|||||||
|
|
||||||
// Sneaky: reference to a mutable static.
|
// Sneaky: reference to a mutable static.
|
||||||
// Allowing this would be a disaster for pattern matching, we could violate exhaustiveness checking!
|
// Allowing this would be a disaster for pattern matching, we could violate exhaustiveness checking!
|
||||||
const SLICE_MUT: &[u8; 1] = { //~ ERROR constant refers to mutable data
|
const SLICE_MUT: &[u8; 1] = { //~ ERROR undefined behavior
|
||||||
|
//~| encountered reference to mutable memory
|
||||||
unsafe { &static_cross_crate::ZERO }
|
unsafe { &static_cross_crate::ZERO }
|
||||||
//~^ WARN shared reference of mutable static is discouraged [static_mut_ref]
|
//~^ WARN shared reference of mutable static is discouraged [static_mut_ref]
|
||||||
};
|
};
|
||||||
|
|
||||||
const U8_MUT: &u8 = { //~ ERROR constant refers to mutable data
|
const U8_MUT: &u8 = { //~ ERROR undefined behavior
|
||||||
|
//~| encountered reference to mutable memory
|
||||||
unsafe { &static_cross_crate::ZERO[0] }
|
unsafe { &static_cross_crate::ZERO[0] }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Also test indirection that reads from other static.
|
// Also test indirection that reads from other static.
|
||||||
const U8_MUT2: &u8 = { //~ ERROR constant refers to mutable data
|
const U8_MUT2: &u8 = { //~ ERROR undefined behavior
|
||||||
|
//~| encountered reference to mutable memory
|
||||||
unsafe { &(*static_cross_crate::ZERO_REF)[0] }
|
unsafe { &(*static_cross_crate::ZERO_REF)[0] }
|
||||||
};
|
};
|
||||||
const U8_MUT3: &u8 = {
|
const U8_MUT3: &u8 = {
|
||||||
|
@ -38,50 +38,61 @@ LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const
|
|||||||
╾ALLOC1<imm>╼ │ ╾──╼
|
╾ALLOC1<imm>╼ │ ╾──╼
|
||||||
}
|
}
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/mutable_references_err.rs:48:33
|
--> $DIR/mutable_references_err.rs:47:1
|
||||||
|
|
|
||||||
|
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: 4, align: 4) {
|
||||||
|
╾ALLOC2<imm>╼ │ ╾──╼
|
||||||
|
}
|
||||||
|
|
||||||
|
note: erroneous constant encountered
|
||||||
|
--> $DIR/mutable_references_err.rs:49:34
|
||||||
|
|
|
|
||||||
LL | const READS_FROM_MUTABLE: i32 = *POINTS_TO_MUTABLE1;
|
LL | const READS_FROM_MUTABLE: i32 = *POINTS_TO_MUTABLE1;
|
||||||
| ^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/mutable_references_err.rs:52:43
|
--> $DIR/mutable_references_err.rs:51: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_err.rs:56:1
|
--> $DIR/mutable_references_err.rs:55: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 _;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: encountered mutable pointer in final value of constant
|
error: encountered mutable pointer in final value of constant
|
||||||
--> $DIR/mutable_references_err.rs:58:1
|
--> $DIR/mutable_references_err.rs:57: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 _;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: encountered mutable pointer in final value of constant
|
error: encountered mutable pointer in final value of constant
|
||||||
--> $DIR/mutable_references_err.rs:60:1
|
--> $DIR/mutable_references_err.rs:59:1
|
||||||
|
|
|
|
||||||
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 _;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: encountered mutable pointer in final value of constant
|
error: encountered mutable pointer in final value of constant
|
||||||
--> $DIR/mutable_references_err.rs:70:1
|
--> $DIR/mutable_references_err.rs:69:1
|
||||||
|
|
|
|
||||||
LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
|
LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: encountered mutable pointer in final value of constant
|
error: encountered mutable pointer in final value of constant
|
||||||
--> $DIR/mutable_references_err.rs:72:1
|
--> $DIR/mutable_references_err.rs:71: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 _ };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: encountered mutable pointer in final value of constant
|
error: encountered mutable pointer in final value of constant
|
||||||
--> $DIR/mutable_references_err.rs:74:1
|
--> $DIR/mutable_references_err.rs:73:1
|
||||||
|
|
|
|
||||||
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -139,42 +150,42 @@ help: skipping check for `const_refs_to_static` feature
|
|||||||
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
|
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/mutable_references_err.rs:52:45
|
--> $DIR/mutable_references_err.rs:51:45
|
||||||
|
|
|
|
||||||
LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
|
LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/mutable_references_err.rs:52:45
|
--> $DIR/mutable_references_err.rs:51: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_err.rs:56:45
|
--> $DIR/mutable_references_err.rs:55: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_err.rs:58:46
|
--> $DIR/mutable_references_err.rs:57: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_err.rs:60:47
|
--> $DIR/mutable_references_err.rs:59: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_err.rs:70:51
|
--> $DIR/mutable_references_err.rs:69: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_err.rs:72:50
|
--> $DIR/mutable_references_err.rs:71:50
|
||||||
|
|
|
|
||||||
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_err.rs:74:51
|
--> $DIR/mutable_references_err.rs:73:51
|
||||||
|
|
|
|
||||||
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -38,50 +38,61 @@ LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const
|
|||||||
╾ALLOC1<imm>╼ │ ╾──────╼
|
╾ALLOC1<imm>╼ │ ╾──────╼
|
||||||
}
|
}
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/mutable_references_err.rs:48:33
|
--> $DIR/mutable_references_err.rs:47:1
|
||||||
|
|
|
||||||
|
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const`
|
||||||
|
|
|
||||||
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
|
= note: the raw bytes of the constant (size: 8, align: 8) {
|
||||||
|
╾ALLOC2<imm>╼ │ ╾──────╼
|
||||||
|
}
|
||||||
|
|
||||||
|
note: erroneous constant encountered
|
||||||
|
--> $DIR/mutable_references_err.rs:49:34
|
||||||
|
|
|
|
||||||
LL | const READS_FROM_MUTABLE: i32 = *POINTS_TO_MUTABLE1;
|
LL | const READS_FROM_MUTABLE: i32 = *POINTS_TO_MUTABLE1;
|
||||||
| ^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/mutable_references_err.rs:52:43
|
--> $DIR/mutable_references_err.rs:51: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_err.rs:56:1
|
--> $DIR/mutable_references_err.rs:55: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 _;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: encountered mutable pointer in final value of constant
|
error: encountered mutable pointer in final value of constant
|
||||||
--> $DIR/mutable_references_err.rs:58:1
|
--> $DIR/mutable_references_err.rs:57: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 _;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: encountered mutable pointer in final value of constant
|
error: encountered mutable pointer in final value of constant
|
||||||
--> $DIR/mutable_references_err.rs:60:1
|
--> $DIR/mutable_references_err.rs:59:1
|
||||||
|
|
|
|
||||||
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 _;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: encountered mutable pointer in final value of constant
|
error: encountered mutable pointer in final value of constant
|
||||||
--> $DIR/mutable_references_err.rs:70:1
|
--> $DIR/mutable_references_err.rs:69:1
|
||||||
|
|
|
|
||||||
LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
|
LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: encountered mutable pointer in final value of constant
|
error: encountered mutable pointer in final value of constant
|
||||||
--> $DIR/mutable_references_err.rs:72:1
|
--> $DIR/mutable_references_err.rs:71: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 _ };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: encountered mutable pointer in final value of constant
|
error: encountered mutable pointer in final value of constant
|
||||||
--> $DIR/mutable_references_err.rs:74:1
|
--> $DIR/mutable_references_err.rs:73:1
|
||||||
|
|
|
|
||||||
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -139,42 +150,42 @@ help: skipping check for `const_refs_to_static` feature
|
|||||||
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
|
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/mutable_references_err.rs:52:45
|
--> $DIR/mutable_references_err.rs:51:45
|
||||||
|
|
|
|
||||||
LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
|
LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
help: skipping check for `const_refs_to_static` feature
|
help: skipping check for `const_refs_to_static` feature
|
||||||
--> $DIR/mutable_references_err.rs:52:45
|
--> $DIR/mutable_references_err.rs:51: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_err.rs:56:45
|
--> $DIR/mutable_references_err.rs:55: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_err.rs:58:46
|
--> $DIR/mutable_references_err.rs:57: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_err.rs:60:47
|
--> $DIR/mutable_references_err.rs:59: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_err.rs:70:51
|
--> $DIR/mutable_references_err.rs:69: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_err.rs:72:50
|
--> $DIR/mutable_references_err.rs:71:50
|
||||||
|
|
|
|
||||||
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_err.rs:74:51
|
--> $DIR/mutable_references_err.rs:73:51
|
||||||
|
|
|
|
||||||
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -44,10 +44,9 @@ unsafe impl Sync for Synced {}
|
|||||||
// Check for consts pointing to mutable memory.
|
// Check for consts pointing to mutable memory.
|
||||||
// These are fine as long as they are not being read.
|
// These are fine as long as they are not being read.
|
||||||
static mut MUTABLE: i32 = 42;
|
static mut MUTABLE: i32 = 42;
|
||||||
const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
|
const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; //~ERROR: undefined behavior
|
||||||
|
//~| encountered reference to mutable memory
|
||||||
const READS_FROM_MUTABLE: i32 = *POINTS_TO_MUTABLE1;
|
const READS_FROM_MUTABLE: i32 = *POINTS_TO_MUTABLE1;
|
||||||
//~^ ERROR: evaluation of constant value failed
|
|
||||||
//~| accesses mutable global memory
|
|
||||||
static mut MUTABLE_REF: &mut i32 = &mut 42;
|
static mut MUTABLE_REF: &mut i32 = &mut 42;
|
||||||
const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
|
const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
|
||||||
//~^ ERROR: evaluation of constant value failed
|
//~^ ERROR: evaluation of constant value failed
|
||||||
|
Loading…
Reference in New Issue
Block a user