Auto merge of #74949 - oli-obk:validate_const_eval_raw, r=RalfJung
Validate constants during `const_eval_raw` This PR implements the groundwork for https://github.com/rust-lang/rust/issues/72396 * constants are now validated during `const_eval_raw` * to prevent cycle errors, we do not validate references to statics anymore beyond the fact that they are not dangling * the `const_eval` query ICEs if used on `static` items * as a side effect promoteds are now evaluated to `ConstValue::Scalar` again (since they are just a reference to the actual promoted allocation in most cases).
This commit is contained in:
commit
5e449b9adf
|
@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::Node;
|
use rustc_hir::Node;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{
|
||||||
read_target_uint, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Pointer,
|
read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer,
|
||||||
};
|
};
|
||||||
use rustc_middle::mir::mono::MonoItem;
|
use rustc_middle::mir::mono::MonoItem;
|
||||||
use rustc_middle::ty::{self, Instance, Ty};
|
use rustc_middle::ty::{self, Instance, Ty};
|
||||||
|
@ -85,10 +85,7 @@ pub fn codegen_static_initializer(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
|
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
|
||||||
let alloc = match cx.tcx.const_eval_poly(def_id)? {
|
let alloc = cx.tcx.eval_static_initializer(def_id)?;
|
||||||
ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => alloc,
|
|
||||||
val => bug!("static const eval returned {:#?}", val),
|
|
||||||
};
|
|
||||||
Ok((const_alloc_to_llvm(cx, alloc), alloc))
|
Ok((const_alloc_to_llvm(cx, alloc), alloc))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ use rustc_ast as ast;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::{AllocId, ConstValue, Pointer, Scalar};
|
use rustc_middle::mir::interpret::ConstValue;
|
||||||
use rustc_middle::mir::AssertKind;
|
use rustc_middle::mir::AssertKind;
|
||||||
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
|
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
|
@ -867,24 +867,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
let ty = constant.literal.ty;
|
let ty = constant.literal.ty;
|
||||||
let size = bx.layout_of(ty).size;
|
let size = bx.layout_of(ty).size;
|
||||||
let scalar = match const_value {
|
let scalar = match const_value {
|
||||||
// Promoted constants are evaluated into a ByRef instead of a Scalar,
|
ConstValue::Scalar(s) => s,
|
||||||
// but we want the scalar value here.
|
_ => span_bug!(
|
||||||
ConstValue::ByRef { alloc, offset } => {
|
span,
|
||||||
let ptr = Pointer::new(AllocId(0), offset);
|
"expected Scalar for promoted asm const, but got {:#?}",
|
||||||
alloc
|
const_value
|
||||||
.read_scalar(&bx, ptr, size)
|
),
|
||||||
.and_then(|s| s.check_init())
|
|
||||||
.unwrap_or_else(|e| {
|
|
||||||
bx.tcx().sess.span_err(
|
|
||||||
span,
|
|
||||||
&format!("Could not evaluate asm const: {}", e),
|
|
||||||
);
|
|
||||||
|
|
||||||
// We are erroring out, just emit a dummy constant.
|
|
||||||
Scalar::from_u64(0)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => span_bug!(span, "expected ByRef for promoted asm const"),
|
|
||||||
};
|
};
|
||||||
let value = scalar.assert_bits(size);
|
let value = scalar.assert_bits(size);
|
||||||
let string = match ty.kind() {
|
let string = match ty.kind() {
|
||||||
|
|
|
@ -21,7 +21,7 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
|
||||||
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
|
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
|
||||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
|
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::ConstEvalResult;
|
use rustc_middle::mir::interpret::EvalToConstValueResult;
|
||||||
use rustc_middle::traits::select;
|
use rustc_middle::traits::select;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
|
||||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
|
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
|
||||||
|
@ -1542,7 +1542,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
substs: SubstsRef<'tcx>,
|
substs: SubstsRef<'tcx>,
|
||||||
promoted: Option<mir::Promoted>,
|
promoted: Option<mir::Promoted>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
) -> ConstEvalResult<'tcx> {
|
) -> EvalToConstValueResult<'tcx> {
|
||||||
let mut original_values = OriginalQueryValues::default();
|
let mut original_values = OriginalQueryValues::default();
|
||||||
let canonical = self.canonicalize_query(&(param_env, substs), &mut original_values);
|
let canonical = self.canonicalize_query(&(param_env, substs), &mut original_values);
|
||||||
|
|
||||||
|
|
|
@ -1474,21 +1474,19 @@ declare_lint_pass!(
|
||||||
UnusedBrokenConst => []
|
UnusedBrokenConst => []
|
||||||
);
|
);
|
||||||
|
|
||||||
fn check_const(cx: &LateContext<'_>, body_id: hir::BodyId) {
|
|
||||||
let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id();
|
|
||||||
// trigger the query once for all constants since that will already report the errors
|
|
||||||
// FIXME: Use ensure here
|
|
||||||
let _ = cx.tcx.const_eval_poly(def_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for UnusedBrokenConst {
|
impl<'tcx> LateLintPass<'tcx> for UnusedBrokenConst {
|
||||||
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
|
||||||
match it.kind {
|
match it.kind {
|
||||||
hir::ItemKind::Const(_, body_id) => {
|
hir::ItemKind::Const(_, body_id) => {
|
||||||
check_const(cx, body_id);
|
let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id();
|
||||||
|
// trigger the query once for all constants since that will already report the errors
|
||||||
|
// FIXME: Use ensure here
|
||||||
|
let _ = cx.tcx.const_eval_poly(def_id);
|
||||||
}
|
}
|
||||||
hir::ItemKind::Static(_, _, body_id) => {
|
hir::ItemKind::Static(_, _, body_id) => {
|
||||||
check_const(cx, body_id);
|
let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id();
|
||||||
|
// FIXME: Use ensure here
|
||||||
|
let _ = cx.tcx.eval_static_initializer(def_id);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{AllocId, Pointer, RawConst, Scalar};
|
use super::{AllocId, ConstAlloc, Pointer, Scalar};
|
||||||
|
|
||||||
use crate::mir::interpret::ConstValue;
|
use crate::mir::interpret::ConstValue;
|
||||||
use crate::ty::{layout, query::TyCtxtAt, tls, FnSig, Ty};
|
use crate::ty::{layout, query::TyCtxtAt, tls, FnSig, Ty};
|
||||||
|
@ -27,8 +27,8 @@ CloneTypeFoldableAndLiftImpls! {
|
||||||
ErrorHandled,
|
ErrorHandled,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
|
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
|
||||||
pub type ConstEvalResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
|
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
|
||||||
|
|
||||||
pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'tcx> {
|
pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'tcx> {
|
||||||
struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
|
struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
|
||||||
|
|
|
@ -118,12 +118,12 @@ use crate::ty::subst::GenericArgKind;
|
||||||
use crate::ty::{self, Instance, Ty, TyCtxt};
|
use crate::ty::{self, Instance, Ty, TyCtxt};
|
||||||
|
|
||||||
pub use self::error::{
|
pub use self::error::{
|
||||||
struct_error, CheckInAllocMsg, ConstEvalRawResult, ConstEvalResult, ErrorHandled, InterpError,
|
struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
|
||||||
InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType, ResourceExhaustionInfo,
|
InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType,
|
||||||
UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
|
ResourceExhaustionInfo, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUninit};
|
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMaybeUninit};
|
||||||
|
|
||||||
pub use self::allocation::{Allocation, AllocationExtra, InitMask, Relocations};
|
pub use self::allocation::{Allocation, AllocationExtra, InitMask, Relocations};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{ConstEvalResult, ErrorHandled, GlobalId};
|
use super::{ErrorHandled, EvalToConstValueResult, GlobalId};
|
||||||
|
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
use crate::ty::subst::{InternalSubsts, SubstsRef};
|
use crate::ty::subst::{InternalSubsts, SubstsRef};
|
||||||
|
@ -10,7 +10,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
|
/// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
|
||||||
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
|
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
|
||||||
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
|
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
|
||||||
pub fn const_eval_poly(self, def_id: DefId) -> ConstEvalResult<'tcx> {
|
pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
|
||||||
// In some situations def_id will have substitutions within scope, but they aren't allowed
|
// In some situations def_id will have substitutions within scope, but they aren't allowed
|
||||||
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
|
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
|
||||||
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
|
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
|
||||||
|
@ -38,7 +38,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
substs: SubstsRef<'tcx>,
|
substs: SubstsRef<'tcx>,
|
||||||
promoted: Option<mir::Promoted>,
|
promoted: Option<mir::Promoted>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
) -> ConstEvalResult<'tcx> {
|
) -> EvalToConstValueResult<'tcx> {
|
||||||
match ty::Instance::resolve_opt_const_arg(self, param_env, def, substs) {
|
match ty::Instance::resolve_opt_const_arg(self, param_env, def, substs) {
|
||||||
Ok(Some(instance)) => {
|
Ok(Some(instance)) => {
|
||||||
let cid = GlobalId { instance, promoted };
|
let cid = GlobalId { instance, promoted };
|
||||||
|
@ -54,7 +54,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
) -> ConstEvalResult<'tcx> {
|
) -> EvalToConstValueResult<'tcx> {
|
||||||
self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span)
|
self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,14 +64,14 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
cid: GlobalId<'tcx>,
|
cid: GlobalId<'tcx>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
) -> ConstEvalResult<'tcx> {
|
) -> EvalToConstValueResult<'tcx> {
|
||||||
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
|
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
|
||||||
// improve caching of queries.
|
// improve caching of queries.
|
||||||
let inputs = self.erase_regions(¶m_env.and(cid));
|
let inputs = self.erase_regions(¶m_env.and(cid));
|
||||||
if let Some(span) = span {
|
if let Some(span) = span {
|
||||||
self.at(span).const_eval_validated(inputs)
|
self.at(span).eval_to_const_value_raw(inputs)
|
||||||
} else {
|
} else {
|
||||||
self.const_eval_validated(inputs)
|
self.eval_to_const_value_raw(inputs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> Result<&'tcx mir::Allocation, ErrorHandled> {
|
) -> Result<&'tcx mir::Allocation, ErrorHandled> {
|
||||||
trace!("eval_to_allocation: Need to compute {:?}", gid);
|
trace!("eval_to_allocation: Need to compute {:?}", gid);
|
||||||
let raw_const = self.const_eval_raw(param_env.and(gid))?;
|
let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?;
|
||||||
Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
|
Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,9 @@ use crate::ty::{ParamEnv, Ty, TyCtxt};
|
||||||
|
|
||||||
use super::{sign_extend, truncate, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
|
use super::{sign_extend, truncate, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
|
||||||
|
|
||||||
/// Represents the result of a raw const operation, pre-validation.
|
/// Represents the result of const evaluation via the `eval_to_allocation` query.
|
||||||
#[derive(Clone, HashStable)]
|
#[derive(Clone, HashStable)]
|
||||||
pub struct RawConst<'tcx> {
|
pub struct ConstAlloc<'tcx> {
|
||||||
// the value lives here, at offset 0, and that allocation definitely is a `AllocKind::Memory`
|
// the value lives here, at offset 0, and that allocation definitely is a `AllocKind::Memory`
|
||||||
// (so you can use `AllocMap::unwrap_memory`).
|
// (so you can use `AllocMap::unwrap_memory`).
|
||||||
pub alloc_id: AllocId,
|
pub alloc_id: AllocId,
|
||||||
|
|
|
@ -707,32 +707,27 @@ rustc_queries! {
|
||||||
}
|
}
|
||||||
|
|
||||||
Other {
|
Other {
|
||||||
/// Evaluates a constant without running sanity checks.
|
/// Evaluates a constant and returns the computed allocation.
|
||||||
///
|
///
|
||||||
/// **Do not use this** outside const eval. Const eval uses this to break query cycles
|
/// **Do not use this** directly, use the `tcx.eval_static_initializer` wrapper.
|
||||||
/// during validation. Please add a comment to every use site explaining why using
|
query eval_to_allocation_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||||
/// `const_eval_validated` isn't sufficient. The returned constant also isn't in a suitable
|
-> EvalToAllocationRawResult<'tcx> {
|
||||||
/// form to be used outside of const eval.
|
|
||||||
query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
|
||||||
-> ConstEvalRawResult<'tcx> {
|
|
||||||
desc { |tcx|
|
desc { |tcx|
|
||||||
"const-evaluating `{}`",
|
"const-evaluating + checking `{}`",
|
||||||
key.value.display(tcx)
|
key.value.display(tcx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Results of evaluating const items or constants embedded in
|
/// Evaluates const items or anonymous constants
|
||||||
/// other items (such as enum variant explicit discriminants).
|
/// (such as enum variant explicit discriminants or array lengths)
|
||||||
///
|
/// into a representation suitable for the type system and const generics.
|
||||||
/// In contrast to `const_eval_raw` this performs some validation on the constant, and
|
|
||||||
/// returns a proper constant that is usable by the rest of the compiler.
|
|
||||||
///
|
///
|
||||||
/// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`,
|
/// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`,
|
||||||
/// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`.
|
/// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`.
|
||||||
query const_eval_validated(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
query eval_to_const_value_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||||
-> ConstEvalResult<'tcx> {
|
-> EvalToConstValueResult<'tcx> {
|
||||||
desc { |tcx|
|
desc { |tcx|
|
||||||
"const-evaluating + checking `{}`",
|
"simplifying constant for the type system `{}`",
|
||||||
key.value.display(tcx)
|
key.value.display(tcx)
|
||||||
}
|
}
|
||||||
cache_on_disk_if(_, opt_result) {
|
cache_on_disk_if(_, opt_result) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLife
|
||||||
use crate::middle::stability::{self, DeprecationEntry};
|
use crate::middle::stability::{self, DeprecationEntry};
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
use crate::mir::interpret::GlobalId;
|
use crate::mir::interpret::GlobalId;
|
||||||
use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult, ConstValue};
|
use crate::mir::interpret::{ConstValue, EvalToAllocationRawResult, EvalToConstValueResult};
|
||||||
use crate::mir::interpret::{LitToConstError, LitToConstInput};
|
use crate::mir::interpret::{LitToConstError, LitToConstInput};
|
||||||
use crate::mir::mono::CodegenUnit;
|
use crate::mir::mono::CodegenUnit;
|
||||||
use crate::traits::query::{
|
use crate::traits::query::{
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr, MemoryExtra};
|
use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr, MemoryExtra};
|
||||||
use crate::interpret::eval_nullary_intrinsic;
|
use crate::interpret::eval_nullary_intrinsic;
|
||||||
use crate::interpret::{
|
use crate::interpret::{
|
||||||
intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, Immediate, InternKind,
|
intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, GlobalId, Immediate,
|
||||||
InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar,
|
InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, Scalar,
|
||||||
ScalarMaybeUninit, StackPopCleanup,
|
ScalarMaybeUninit, StackPopCleanup,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,6 +104,8 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This function converts an interpreter value into a constant that is meant for use in the
|
||||||
|
/// type system.
|
||||||
pub(super) fn op_to_const<'tcx>(
|
pub(super) fn op_to_const<'tcx>(
|
||||||
ecx: &CompileTimeEvalContext<'_, 'tcx>,
|
ecx: &CompileTimeEvalContext<'_, 'tcx>,
|
||||||
op: OpTy<'tcx>,
|
op: OpTy<'tcx>,
|
||||||
|
@ -182,63 +184,37 @@ pub(super) fn op_to_const<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_and_turn_into_const<'tcx>(
|
fn turn_into_const_value<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
constant: RawConst<'tcx>,
|
constant: ConstAlloc<'tcx>,
|
||||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||||
) -> ::rustc_middle::mir::interpret::ConstEvalResult<'tcx> {
|
) -> ConstValue<'tcx> {
|
||||||
let cid = key.value;
|
let cid = key.value;
|
||||||
let def_id = cid.instance.def.def_id();
|
let def_id = cid.instance.def.def_id();
|
||||||
let is_static = tcx.is_static(def_id);
|
let is_static = tcx.is_static(def_id);
|
||||||
let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, is_static);
|
let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, is_static);
|
||||||
let val = (|| {
|
|
||||||
let mplace = ecx.raw_const_to_mplace(constant)?;
|
|
||||||
|
|
||||||
// FIXME do not validate promoteds until a decision on
|
let mplace = ecx.raw_const_to_mplace(constant).expect(
|
||||||
// https://github.com/rust-lang/rust/issues/67465 is made
|
"can only fail if layout computation failed, \
|
||||||
if cid.promoted.is_none() {
|
which should have given a good error before ever invoking this function",
|
||||||
let mut ref_tracking = RefTracking::new(mplace);
|
);
|
||||||
while let Some((mplace, path)) = ref_tracking.todo.pop() {
|
assert!(
|
||||||
ecx.const_validate_operand(
|
!is_static || cid.promoted.is_some(),
|
||||||
mplace.into(),
|
"the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
|
||||||
path,
|
);
|
||||||
&mut ref_tracking,
|
// Turn this into a proper constant.
|
||||||
/*may_ref_to_static*/ ecx.memory.extra.can_access_statics,
|
op_to_const(&ecx, mplace.into())
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Now that we validated, turn this into a proper constant.
|
|
||||||
// Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
|
|
||||||
// whether they become immediates.
|
|
||||||
if is_static || cid.promoted.is_some() {
|
|
||||||
let ptr = mplace.ptr.assert_ptr();
|
|
||||||
Ok(ConstValue::ByRef {
|
|
||||||
alloc: ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory(),
|
|
||||||
offset: ptr.offset,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok(op_to_const(&ecx, mplace.into()))
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
val.map_err(|error| {
|
|
||||||
let err = ConstEvalErr::new(&ecx, error, None);
|
|
||||||
err.struct_error(ecx.tcx, "it is undefined behavior to use this value", |mut diag| {
|
|
||||||
diag.note(note_on_undefined_behavior_error());
|
|
||||||
diag.emit();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_eval_validated_provider<'tcx>(
|
pub fn eval_to_const_value_raw_provider<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||||
) -> ::rustc_middle::mir::interpret::ConstEvalResult<'tcx> {
|
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
|
||||||
// see comment in const_eval_raw_provider for what we're doing here
|
// see comment in const_eval_raw_provider for what we're doing here
|
||||||
if key.param_env.reveal() == Reveal::All {
|
if key.param_env.reveal() == Reveal::All {
|
||||||
let mut key = key;
|
let mut key = key;
|
||||||
key.param_env = key.param_env.with_user_facing();
|
key.param_env = key.param_env.with_user_facing();
|
||||||
match tcx.const_eval_validated(key) {
|
match tcx.eval_to_const_value_raw(key) {
|
||||||
// try again with reveal all as requested
|
// try again with reveal all as requested
|
||||||
Err(ErrorHandled::TooGeneric) => {}
|
Err(ErrorHandled::TooGeneric) => {}
|
||||||
// deduplicate calls
|
// deduplicate calls
|
||||||
|
@ -261,13 +237,13 @@ pub fn const_eval_validated_provider<'tcx>(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tcx.const_eval_raw(key).and_then(|val| validate_and_turn_into_const(tcx, val, key))
|
tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_eval_raw_provider<'tcx>(
|
pub fn eval_to_allocation_raw_provider<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||||
) -> ::rustc_middle::mir::interpret::ConstEvalRawResult<'tcx> {
|
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
|
||||||
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
|
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
|
||||||
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
|
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
|
||||||
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was
|
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was
|
||||||
|
@ -279,7 +255,7 @@ pub fn const_eval_raw_provider<'tcx>(
|
||||||
if key.param_env.reveal() == Reveal::All {
|
if key.param_env.reveal() == Reveal::All {
|
||||||
let mut key = key;
|
let mut key = key;
|
||||||
key.param_env = key.param_env.with_user_facing();
|
key.param_env = key.param_env.with_user_facing();
|
||||||
match tcx.const_eval_raw(key) {
|
match tcx.eval_to_allocation_raw(key) {
|
||||||
// try again with reveal all as requested
|
// try again with reveal all as requested
|
||||||
Err(ErrorHandled::TooGeneric) => {}
|
Err(ErrorHandled::TooGeneric) => {}
|
||||||
// deduplicate calls
|
// deduplicate calls
|
||||||
|
@ -318,9 +294,8 @@ pub fn const_eval_raw_provider<'tcx>(
|
||||||
);
|
);
|
||||||
|
|
||||||
let res = ecx.load_mir(cid.instance.def, cid.promoted);
|
let res = ecx.load_mir(cid.instance.def, cid.promoted);
|
||||||
res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body))
|
match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) {
|
||||||
.map(|place| RawConst { alloc_id: place.ptr.assert_ptr().alloc_id, ty: place.layout.ty })
|
Err(error) => {
|
||||||
.map_err(|error| {
|
|
||||||
let err = ConstEvalErr::new(&ecx, error, None);
|
let err = ConstEvalErr::new(&ecx, error, None);
|
||||||
// errors in statics are always emitted as fatal errors
|
// errors in statics are always emitted as fatal errors
|
||||||
if is_static {
|
if is_static {
|
||||||
|
@ -342,7 +317,7 @@ pub fn const_eval_raw_provider<'tcx>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
v
|
Err(v)
|
||||||
} else if let Some(def) = def.as_local() {
|
} else if let Some(def) = def.as_local() {
|
||||||
// constant defined in this crate, we can figure out a lint level!
|
// constant defined in this crate, we can figure out a lint level!
|
||||||
match tcx.def_kind(def.did.to_def_id()) {
|
match tcx.def_kind(def.did.to_def_id()) {
|
||||||
|
@ -356,12 +331,12 @@ pub fn const_eval_raw_provider<'tcx>(
|
||||||
// compatibility hazard
|
// compatibility hazard
|
||||||
DefKind::Const | DefKind::AssocConst => {
|
DefKind::Const | DefKind::AssocConst => {
|
||||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
|
||||||
err.report_as_lint(
|
Err(err.report_as_lint(
|
||||||
tcx.at(tcx.def_span(def.did)),
|
tcx.at(tcx.def_span(def.did)),
|
||||||
"any use of this value will cause an error",
|
"any use of this value will cause an error",
|
||||||
hir_id,
|
hir_id,
|
||||||
Some(err.span),
|
Some(err.span),
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
// promoting runtime code is only allowed to error if it references broken
|
// promoting runtime code is only allowed to error if it references broken
|
||||||
// constants any other kind of error will be reported to the user as a
|
// constants any other kind of error will be reported to the user as a
|
||||||
|
@ -370,31 +345,65 @@ pub fn const_eval_raw_provider<'tcx>(
|
||||||
if let Some(p) = cid.promoted {
|
if let Some(p) = cid.promoted {
|
||||||
let span = tcx.promoted_mir_of_opt_const_arg(def.to_global())[p].span;
|
let span = tcx.promoted_mir_of_opt_const_arg(def.to_global())[p].span;
|
||||||
if let err_inval!(ReferencedConstant) = err.error {
|
if let err_inval!(ReferencedConstant) = err.error {
|
||||||
err.report_as_error(
|
Err(err.report_as_error(
|
||||||
tcx.at(span),
|
tcx.at(span),
|
||||||
"evaluation of constant expression failed",
|
"evaluation of constant expression failed",
|
||||||
)
|
))
|
||||||
} else {
|
} else {
|
||||||
err.report_as_lint(
|
Err(err.report_as_lint(
|
||||||
tcx.at(span),
|
tcx.at(span),
|
||||||
"reaching this expression at runtime will panic or abort",
|
"reaching this expression at runtime will panic or abort",
|
||||||
tcx.hir().local_def_id_to_hir_id(def.did),
|
tcx.hir().local_def_id_to_hir_id(def.did),
|
||||||
Some(err.span),
|
Some(err.span),
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
// anything else (array lengths, enum initializers, constant patterns) are
|
// anything else (array lengths, enum initializers, constant patterns) are
|
||||||
// reported as hard errors
|
// reported as hard errors
|
||||||
} else {
|
} else {
|
||||||
err.report_as_error(
|
Err(err.report_as_error(
|
||||||
ecx.tcx.at(ecx.cur_span()),
|
ecx.tcx.at(ecx.cur_span()),
|
||||||
"evaluation of constant value failed",
|
"evaluation of constant value failed",
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// use of broken constant from other crate
|
// use of broken constant from other crate
|
||||||
err.report_as_error(ecx.tcx.at(ecx.cur_span()), "could not evaluate constant")
|
Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), "could not evaluate constant"))
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
Ok(mplace) => {
|
||||||
|
// Since evaluation had no errors, valiate the resulting constant:
|
||||||
|
let validation = try {
|
||||||
|
// FIXME do not validate promoteds until a decision on
|
||||||
|
// https://github.com/rust-lang/rust/issues/67465 is made
|
||||||
|
if cid.promoted.is_none() {
|
||||||
|
let mut ref_tracking = RefTracking::new(mplace);
|
||||||
|
while let Some((mplace, path)) = ref_tracking.todo.pop() {
|
||||||
|
ecx.const_validate_operand(
|
||||||
|
mplace.into(),
|
||||||
|
path,
|
||||||
|
&mut ref_tracking,
|
||||||
|
/*may_ref_to_static*/ ecx.memory.extra.can_access_statics,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Err(error) = validation {
|
||||||
|
// Validation failed, report an error
|
||||||
|
let err = ConstEvalErr::new(&ecx, error, None);
|
||||||
|
Err(err.struct_error(
|
||||||
|
ecx.tcx,
|
||||||
|
"it is undefined behavior to use this value",
|
||||||
|
|mut diag| {
|
||||||
|
diag.note(note_on_undefined_behavior_error());
|
||||||
|
diag.emit();
|
||||||
|
},
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
// Convert to raw constant
|
||||||
|
Ok(ConstAlloc { alloc_id: mplace.ptr.assert_ptr().alloc_id, ty: mplace.layout.ty })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
|
||||||
|
|
||||||
let gid = GlobalId { instance, promoted: None };
|
let gid = GlobalId { instance, promoted: None };
|
||||||
|
|
||||||
let place = self.const_eval_raw(gid)?;
|
let place = self.eval_to_allocation(gid)?;
|
||||||
|
|
||||||
self.copy_op(place.into(), dest)?;
|
self.copy_op(place.into(), dest)?;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ use rustc_span::{Pos, Span};
|
||||||
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
|
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
|
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, Operand, Place, PlaceTy,
|
||||||
ScalarMaybeUninit, StackPopJump,
|
ScalarMaybeUninit, StackPopJump,
|
||||||
};
|
};
|
||||||
use crate::transform::validate::equal_up_to_regions;
|
use crate::transform::validate::equal_up_to_regions;
|
||||||
|
@ -875,32 +875,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn const_eval(
|
pub fn eval_to_allocation(
|
||||||
&self,
|
|
||||||
gid: GlobalId<'tcx>,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
|
||||||
// For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
|
|
||||||
// and thus don't care about the parameter environment. While we could just use
|
|
||||||
// `self.param_env`, that would mean we invoke the query to evaluate the static
|
|
||||||
// with different parameter environments, thus causing the static to be evaluated
|
|
||||||
// multiple times.
|
|
||||||
let param_env = if self.tcx.is_static(gid.instance.def_id()) {
|
|
||||||
ty::ParamEnv::reveal_all()
|
|
||||||
} else {
|
|
||||||
self.param_env
|
|
||||||
};
|
|
||||||
let val = self.tcx.const_eval_global_id(param_env, gid, Some(self.tcx.span))?;
|
|
||||||
|
|
||||||
// Even though `ecx.const_eval` is called from `const_to_op` we can never have a
|
|
||||||
// recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
|
|
||||||
// return `ConstValue::Unevaluated`, which is the only way that `const_to_op` will call
|
|
||||||
// `ecx.const_eval`.
|
|
||||||
let const_ = ty::Const { val: ty::ConstKind::Value(val), ty };
|
|
||||||
self.const_to_op(&const_, None)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn const_eval_raw(
|
|
||||||
&self,
|
&self,
|
||||||
gid: GlobalId<'tcx>,
|
gid: GlobalId<'tcx>,
|
||||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
||||||
|
@ -914,14 +889,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
} else {
|
} else {
|
||||||
self.param_env
|
self.param_env
|
||||||
};
|
};
|
||||||
// We use `const_eval_raw` here, and get an unvalidated result. That is okay:
|
let val = self.tcx.eval_to_allocation_raw(param_env.and(gid))?;
|
||||||
// Our result will later be validated anyway, and there seems no good reason
|
|
||||||
// to have to fail early here. This is also more consistent with
|
|
||||||
// `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
|
|
||||||
// FIXME: We can hit delay_span_bug if this is an invalid const, interning finds
|
|
||||||
// that problem, but we never run validation to show an error. Can we ensure
|
|
||||||
// this does not happen?
|
|
||||||
let val = self.tcx.const_eval_raw(param_env.and(gid))?;
|
|
||||||
self.raw_const_to_mplace(val)
|
self.raw_const_to_mplace(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
sym::type_name => self.tcx.mk_static_str(),
|
sym::type_name => self.tcx.mk_static_str(),
|
||||||
_ => bug!("already checked for nullary intrinsics"),
|
_ => bug!("already checked for nullary intrinsics"),
|
||||||
};
|
};
|
||||||
let val = self.const_eval(gid, ty)?;
|
let val =
|
||||||
|
self.tcx.const_eval_global_id(self.param_env, gid, Some(self.tcx.span))?;
|
||||||
|
let const_ = ty::Const { val: ty::ConstKind::Value(val), ty };
|
||||||
|
let val = self.const_to_op(&const_, None)?;
|
||||||
self.copy_op(val, dest)?;
|
self.copy_op(val, dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -469,7 +469,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
||||||
// Notice that every static has two `AllocId` that will resolve to the same
|
// Notice that every static has two `AllocId` that will resolve to the same
|
||||||
// thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID,
|
// thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID,
|
||||||
// and the other one is maps to `GlobalAlloc::Memory`, this is returned by
|
// and the other one is maps to `GlobalAlloc::Memory`, this is returned by
|
||||||
// `const_eval_raw` and it is the "resolved" ID.
|
// `eval_static_initializer` and it is the "resolved" ID.
|
||||||
// The resolved ID is never used by the interpreted program, it is hidden.
|
// The resolved ID is never used by the interpreted program, it is hidden.
|
||||||
// This is relied upon for soundness of const-patterns; a pointer to the resolved
|
// This is relied upon for soundness of const-patterns; a pointer to the resolved
|
||||||
// ID would "sidestep" the checks that make sure consts do not point to statics!
|
// ID would "sidestep" the checks that make sure consts do not point to statics!
|
||||||
|
|
|
@ -553,13 +553,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
ty::ConstKind::Error(_) => throw_inval!(TypeckError(ErrorReported)),
|
ty::ConstKind::Error(_) => throw_inval!(TypeckError(ErrorReported)),
|
||||||
ty::ConstKind::Unevaluated(def, substs, promoted) => {
|
ty::ConstKind::Unevaluated(def, substs, promoted) => {
|
||||||
let instance = self.resolve(def.did, substs)?;
|
let instance = self.resolve(def.did, substs)?;
|
||||||
// We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation.
|
return Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into());
|
||||||
// The reason we use `const_eval_raw` everywhere else is to prevent cycles during
|
|
||||||
// validation, because validation automatically reads through any references, thus
|
|
||||||
// potentially requiring the current static to be evaluated again. This is not a
|
|
||||||
// problem here, because we are building an operand which means an actual read is
|
|
||||||
// happening.
|
|
||||||
return Ok(self.const_eval(GlobalId { instance, promoted }, val.ty)?);
|
|
||||||
}
|
}
|
||||||
ty::ConstKind::Infer(..)
|
ty::ConstKind::Infer(..)
|
||||||
| ty::ConstKind::Bound(..)
|
| ty::ConstKind::Bound(..)
|
||||||
|
|
|
@ -13,9 +13,9 @@ use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
|
||||||
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
|
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
mir_assign_valid_types, truncate, AllocId, AllocMap, Allocation, AllocationExtra, ImmTy,
|
mir_assign_valid_types, truncate, AllocId, AllocMap, Allocation, AllocationExtra, ConstAlloc,
|
||||||
Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer,
|
ImmTy, Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand,
|
||||||
PointerArithmetic, RawConst, Scalar, ScalarMaybeUninit,
|
Pointer, PointerArithmetic, Scalar, ScalarMaybeUninit,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
||||||
|
@ -1120,7 +1120,7 @@ where
|
||||||
|
|
||||||
pub fn raw_const_to_mplace(
|
pub fn raw_const_to_mplace(
|
||||||
&self,
|
&self,
|
||||||
raw: RawConst<'tcx>,
|
raw: ConstAlloc<'tcx>,
|
||||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
||||||
// This must be an allocation in `tcx`
|
// This must be an allocation in `tcx`
|
||||||
let _ = self.tcx.global_alloc(raw.alloc_id);
|
let _ = self.tcx.global_alloc(raw.alloc_id);
|
||||||
|
|
|
@ -425,26 +425,28 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
let alloc_kind = self.ecx.tcx.get_global_alloc(ptr.alloc_id);
|
let alloc_kind = self.ecx.tcx.get_global_alloc(ptr.alloc_id);
|
||||||
if let Some(GlobalAlloc::Static(did)) = alloc_kind {
|
if let Some(GlobalAlloc::Static(did)) = alloc_kind {
|
||||||
assert!(!self.ecx.tcx.is_thread_local_static(did));
|
assert!(!self.ecx.tcx.is_thread_local_static(did));
|
||||||
// See const_eval::machine::MemoryExtra::can_access_statics for why
|
assert!(self.ecx.tcx.is_static(did));
|
||||||
// this check is so important.
|
if self.may_ref_to_static {
|
||||||
// This check is reachable when the const just referenced the static,
|
// We skip checking other statics. These statics must be sound by
|
||||||
// but never read it (so we never entered `before_access_global`).
|
// themselves, and the only way to get broken statics here is by using
|
||||||
// We also need to do it here instead of going on to avoid running
|
// unsafe code.
|
||||||
// into the `before_access_global` check during validation.
|
// The reasons we don't check other statics is twofold. For one, in all
|
||||||
if !self.may_ref_to_static && self.ecx.tcx.is_static(did) {
|
// 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
|
||||||
|
// and that static refers back to us.
|
||||||
|
// We might miss const-invalid data,
|
||||||
|
// but things are still sound otherwise (in particular re: consts
|
||||||
|
// referring to statics).
|
||||||
|
return Ok(());
|
||||||
|
} else {
|
||||||
|
// See const_eval::machine::MemoryExtra::can_access_statics for why
|
||||||
|
// this check is so important.
|
||||||
|
// This check is reachable when the const just referenced the static,
|
||||||
|
// but never read it (so we never entered `before_access_global`).
|
||||||
throw_validation_failure!(self.path,
|
throw_validation_failure!(self.path,
|
||||||
{ "a {} pointing to a static variable", kind }
|
{ "a {} pointing to a static variable", kind }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// `extern static` cannot be validated as they have no body.
|
|
||||||
// FIXME: Statics from other crates are also skipped.
|
|
||||||
// They might be checked at a different type, but for now we
|
|
||||||
// want to avoid recursing too deeply. We might miss const-invalid data,
|
|
||||||
// but things are still sound otherwise (in particular re: consts
|
|
||||||
// referring to statics).
|
|
||||||
if !did.is_local() || self.ecx.tcx.is_foreign_item(did) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Proceed recursively even for ZST, no reason to skip them!
|
// Proceed recursively even for ZST, no reason to skip them!
|
||||||
|
|
|
@ -53,8 +53,8 @@ pub fn provide(providers: &mut Providers) {
|
||||||
transform::provide(providers);
|
transform::provide(providers);
|
||||||
monomorphize::partitioning::provide(providers);
|
monomorphize::partitioning::provide(providers);
|
||||||
monomorphize::polymorphize::provide(providers);
|
monomorphize::polymorphize::provide(providers);
|
||||||
providers.const_eval_validated = const_eval::const_eval_validated_provider;
|
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
|
||||||
providers.const_eval_raw = const_eval::const_eval_raw_provider;
|
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
|
||||||
providers.const_caller_location = const_eval::const_caller_location;
|
providers.const_caller_location = const_eval::const_caller_location;
|
||||||
providers.destructure_const = |tcx, param_env_and_value| {
|
providers.destructure_const = |tcx, param_env_and_value| {
|
||||||
let (param_env, value) = param_env_and_value.into_parts();
|
let (param_env, value) = param_env_and_value.into_parts();
|
||||||
|
|
|
@ -364,8 +364,10 @@ fn collect_items_rec<'tcx>(
|
||||||
|
|
||||||
recursion_depth_reset = None;
|
recursion_depth_reset = None;
|
||||||
|
|
||||||
if let Ok(val) = tcx.const_eval_poly(def_id) {
|
if let Ok(alloc) = tcx.eval_static_initializer(def_id) {
|
||||||
collect_const_value(tcx, val, &mut neighbors);
|
for &((), id) in alloc.relocations().values() {
|
||||||
|
collect_miri(tcx, id, &mut neighbors);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MonoItem::Fn(instance) => {
|
MonoItem::Fn(instance) => {
|
||||||
|
|
|
@ -631,14 +631,11 @@ pub fn write_allocations<'tcx>(
|
||||||
None => write!(w, " (deallocated)")?,
|
None => write!(w, " (deallocated)")?,
|
||||||
Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {})", inst)?,
|
Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {})", inst)?,
|
||||||
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
|
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
|
||||||
match tcx.const_eval_poly(did) {
|
match tcx.eval_static_initializer(did) {
|
||||||
Ok(ConstValue::ByRef { alloc, .. }) => {
|
Ok(alloc) => {
|
||||||
write!(w, " (static: {}, ", tcx.def_path_str(did))?;
|
write!(w, " (static: {}, ", tcx.def_path_str(did))?;
|
||||||
write_allocation_track_relocs(w, alloc)?;
|
write_allocation_track_relocs(w, alloc)?;
|
||||||
}
|
}
|
||||||
Ok(_) => {
|
|
||||||
span_bug!(tcx.def_span(did), " static item without `ByRef` initializer")
|
|
||||||
}
|
|
||||||
Err(_) => write!(
|
Err(_) => write!(
|
||||||
w,
|
w,
|
||||||
" (static: {}, error during initializer evaluation)",
|
" (static: {}, error during initializer evaluation)",
|
||||||
|
|
|
@ -111,7 +111,6 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
|
||||||
use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||||
use rustc_infer::infer::{InferCtxt, InferOk, InferResult, RegionVariableOrigin, TyCtxtInferExt};
|
use rustc_infer::infer::{InferCtxt, InferOk, InferResult, RegionVariableOrigin, TyCtxtInferExt};
|
||||||
use rustc_middle::hir::map::blocks::FnLikeNode;
|
use rustc_middle::hir::map::blocks::FnLikeNode;
|
||||||
use rustc_middle::mir::interpret::ConstValue;
|
|
||||||
use rustc_middle::ty::adjustment::{
|
use rustc_middle::ty::adjustment::{
|
||||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
|
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
|
||||||
};
|
};
|
||||||
|
@ -2070,8 +2069,8 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: S
|
||||||
// `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
|
// `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
|
||||||
// the consumer's responsibility to ensure all bytes that have been read
|
// the consumer's responsibility to ensure all bytes that have been read
|
||||||
// have defined values.
|
// have defined values.
|
||||||
match tcx.const_eval_poly(id.to_def_id()) {
|
match tcx.eval_static_initializer(id.to_def_id()) {
|
||||||
Ok(ConstValue::ByRef { alloc, .. }) => {
|
Ok(alloc) => {
|
||||||
if alloc.relocations().len() != 0 {
|
if alloc.relocations().len() != 0 {
|
||||||
let msg = "statics with a custom `#[link_section]` must be a \
|
let msg = "statics with a custom `#[link_section]` must be a \
|
||||||
simple list of bytes on the wasm target with no \
|
simple list of bytes on the wasm target with no \
|
||||||
|
@ -2079,7 +2078,6 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: S
|
||||||
tcx.sess.span_err(span, msg);
|
tcx.sess.span_err(span, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(_) => bug!("Matching on non-ByRef static"),
|
|
||||||
Err(_) => {}
|
Err(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
// This checks the constants from {low,high}_align_const, they share the same
|
// This checks the constants from {low,high}_align_const, they share the same
|
||||||
// constant, but the alignment differs, so the higher one should be used
|
// constant, but the alignment differs, so the higher one should be used
|
||||||
// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @alloc20, i32 0, i32 0, i32 0), {{.*}}
|
// CHECK: [[LOW_HIGH:@alloc[0-9]+]] = {{.*}}, align 4
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
// repr(i16) is required for the {low,high}_align_const test
|
// repr(i16) is required for the {low,high}_align_const test
|
||||||
|
@ -43,7 +43,7 @@ pub fn inline_enum_const() -> E<i8, i16> {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn low_align_const() -> E<i16, [i16; 3]> {
|
pub fn low_align_const() -> E<i16, [i16; 3]> {
|
||||||
// Check that low_align_const and high_align_const use the same constant
|
// Check that low_align_const and high_align_const use the same constant
|
||||||
// CHECK: load %"E<i16, [i16; 3]>"*, %"E<i16, [i16; 3]>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, [i16; 3]>"**),
|
// CHECK: memcpy.p0i8.p0i8.i{{(32|64)}}(i8* align 2 %1, i8* align 2 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0), i{{(32|64)}} 8, i1 false)
|
||||||
*&E::A(0)
|
*&E::A(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,6 @@ pub fn low_align_const() -> E<i16, [i16; 3]> {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn high_align_const() -> E<i16, i32> {
|
pub fn high_align_const() -> E<i16, i32> {
|
||||||
// Check that low_align_const and high_align_const use the same constant
|
// Check that low_align_const and high_align_const use the same constant
|
||||||
// CHECK: load %"E<i16, i32>"*, %"E<i16, i32>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, i32>"**),
|
// CHECK: memcpy.p0i8.p0i8.i{{(32|64)}}(i8* align 4 %1, i8* align 4 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0), i{{(32|64)}} 8, i1 false)
|
||||||
*&E::A(0)
|
*&E::A(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::intrinsics;
|
||||||
|
|
||||||
struct Foo {
|
struct Foo {
|
||||||
bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
||||||
//~^ ERROR cycle detected when const-evaluating + checking
|
//~^ ERROR cycle detected when simplifying constant for the type system
|
||||||
x: usize,
|
x: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ impl Tr for str {
|
||||||
type Arr = [u8; 8];
|
type Arr = [u8; 8];
|
||||||
#[cfg(cfail)]
|
#[cfg(cfail)]
|
||||||
type Arr = [u8; Self::C];
|
type Arr = [u8; Self::C];
|
||||||
//[cfail]~^ ERROR cycle detected when const-evaluating
|
//[cfail]~^ ERROR cycle detected when simplifying constant
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
error[E0391]: cycle detected when normalizing `<() as Tr>::A`
|
error[E0391]: cycle detected when normalizing `<() as Tr>::A`
|
||||||
|
|
|
|
||||||
note: ...which requires const-evaluating + checking `Tr::A`...
|
note: ...which requires simplifying constant for the type system `Tr::A`...
|
||||||
|
--> $DIR/defaults-cyclic-fail.rs:6:5
|
||||||
|
|
|
||||||
|
LL | const A: u8 = Self::B;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires simplifying constant for the type system `Tr::A`...
|
||||||
--> $DIR/defaults-cyclic-fail.rs:6:5
|
--> $DIR/defaults-cyclic-fail.rs:6:5
|
||||||
|
|
|
|
||||||
LL | const A: u8 = Self::B;
|
LL | const A: u8 = Self::B;
|
||||||
|
@ -8,15 +13,15 @@ LL | const A: u8 = Self::B;
|
||||||
note: ...which requires const-evaluating + checking `Tr::A`...
|
note: ...which requires const-evaluating + checking `Tr::A`...
|
||||||
--> $DIR/defaults-cyclic-fail.rs:6:5
|
--> $DIR/defaults-cyclic-fail.rs:6:5
|
||||||
|
|
|
|
||||||
LL | const A: u8 = Self::B;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `Tr::A`...
|
|
||||||
--> $DIR/defaults-cyclic-fail.rs:6:5
|
|
||||||
|
|
|
||||||
LL | const A: u8 = Self::B;
|
LL | const A: u8 = Self::B;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `<() as Tr>::B`...
|
= note: ...which requires normalizing `<() as Tr>::B`...
|
||||||
note: ...which requires const-evaluating + checking `Tr::B`...
|
note: ...which requires simplifying constant for the type system `Tr::B`...
|
||||||
|
--> $DIR/defaults-cyclic-fail.rs:8:5
|
||||||
|
|
|
||||||
|
LL | const B: u8 = Self::A;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires simplifying constant for the type system `Tr::B`...
|
||||||
--> $DIR/defaults-cyclic-fail.rs:8:5
|
--> $DIR/defaults-cyclic-fail.rs:8:5
|
||||||
|
|
|
|
||||||
LL | const B: u8 = Self::A;
|
LL | const B: u8 = Self::A;
|
||||||
|
@ -24,15 +29,10 @@ LL | const B: u8 = Self::A;
|
||||||
note: ...which requires const-evaluating + checking `Tr::B`...
|
note: ...which requires const-evaluating + checking `Tr::B`...
|
||||||
--> $DIR/defaults-cyclic-fail.rs:8:5
|
--> $DIR/defaults-cyclic-fail.rs:8:5
|
||||||
|
|
|
|
||||||
LL | const B: u8 = Self::A;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `Tr::B`...
|
|
||||||
--> $DIR/defaults-cyclic-fail.rs:8:5
|
|
||||||
|
|
|
||||||
LL | const B: u8 = Self::A;
|
LL | const B: u8 = Self::A;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which again requires normalizing `<() as Tr>::A`, completing the cycle
|
= note: ...which again requires normalizing `<() as Tr>::A`, completing the cycle
|
||||||
note: cycle used when const-evaluating `main::promoted[2]`
|
note: cycle used when const-evaluating + checking `main::promoted[2]`
|
||||||
--> $DIR/defaults-cyclic-fail.rs:14:1
|
--> $DIR/defaults-cyclic-fail.rs:14:1
|
||||||
|
|
|
|
||||||
LL | fn main() {
|
LL | fn main() {
|
||||||
|
|
|
@ -1,21 +1,26 @@
|
||||||
error[E0391]: cycle detected when const-evaluating + checking `IMPL_REF_BAR`
|
error[E0391]: cycle detected when simplifying constant for the type system `IMPL_REF_BAR`
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
|
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
|
||||||
|
|
|
|
||||||
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
|
note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`...
|
||||||
|
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
|
||||||
|
|
|
||||||
|
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
|
note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
|
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
|
||||||
|
|
|
|
||||||
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `IMPL_REF_BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
|
|
||||||
|
|
|
||||||
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
= note: ...which requires normalizing `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
||||||
note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
||||||
|
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
||||||
|
|
|
||||||
|
LL | const BAR: u32 = IMPL_REF_BAR;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
||||||
|
|
|
|
||||||
LL | const BAR: u32 = IMPL_REF_BAR;
|
LL | const BAR: u32 = IMPL_REF_BAR;
|
||||||
|
@ -25,18 +30,13 @@ note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-a
|
||||||
|
|
|
|
||||||
LL | const BAR: u32 = IMPL_REF_BAR;
|
LL | const BAR: u32 = IMPL_REF_BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
|
||||||
|
|
|
||||||
LL | const BAR: u32 = IMPL_REF_BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires optimizing MIR for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
note: ...which requires optimizing MIR for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
||||||
|
|
|
|
||||||
LL | const BAR: u32 = IMPL_REF_BAR;
|
LL | const BAR: u32 = IMPL_REF_BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `IMPL_REF_BAR`...
|
= note: ...which requires normalizing `IMPL_REF_BAR`...
|
||||||
= note: ...which again requires const-evaluating + checking `IMPL_REF_BAR`, completing the cycle
|
= note: ...which again requires simplifying constant for the type system `IMPL_REF_BAR`, completing the cycle
|
||||||
= note: cycle used when running analysis passes on this crate
|
= note: cycle used when running analysis passes on this crate
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
|
@ -1,21 +1,26 @@
|
||||||
error[E0391]: cycle detected when const-evaluating + checking `DEFAULT_REF_BAR`
|
error[E0391]: cycle detected when simplifying constant for the type system `DEFAULT_REF_BAR`
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
|
||||||
|
|
|
|
||||||
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
|
note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`...
|
||||||
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
|
||||||
|
|
|
||||||
|
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
|
note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
|
||||||
|
|
|
|
||||||
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `DEFAULT_REF_BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
|
|
||||||
|
|
|
||||||
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `<GlobalDefaultRef as FooDefault>::BAR`...
|
= note: ...which requires normalizing `<GlobalDefaultRef as FooDefault>::BAR`...
|
||||||
note: ...which requires const-evaluating + checking `FooDefault::BAR`...
|
note: ...which requires simplifying constant for the type system `FooDefault::BAR`...
|
||||||
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
||||||
|
|
|
||||||
|
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires simplifying constant for the type system `FooDefault::BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
||||||
|
|
|
|
||||||
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
||||||
|
@ -25,18 +30,13 @@ note: ...which requires const-evaluating + checking `FooDefault::BAR`...
|
||||||
|
|
|
|
||||||
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating `FooDefault::BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
|
||||||
|
|
|
||||||
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires optimizing MIR for `FooDefault::BAR`...
|
note: ...which requires optimizing MIR for `FooDefault::BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
||||||
|
|
|
|
||||||
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `DEFAULT_REF_BAR`...
|
= note: ...which requires normalizing `DEFAULT_REF_BAR`...
|
||||||
= note: ...which again requires const-evaluating + checking `DEFAULT_REF_BAR`, completing the cycle
|
= note: ...which again requires simplifying constant for the type system `DEFAULT_REF_BAR`, completing the cycle
|
||||||
= note: cycle used when running analysis passes on this crate
|
= note: cycle used when running analysis passes on this crate
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
|
@ -1,21 +1,26 @@
|
||||||
error[E0391]: cycle detected when const-evaluating + checking `TRAIT_REF_BAR`
|
error[E0391]: cycle detected when simplifying constant for the type system `TRAIT_REF_BAR`
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
|
||||||
|
|
|
|
||||||
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
|
note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`...
|
||||||
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
|
||||||
|
|
|
||||||
|
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
|
note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
|
||||||
|
|
|
|
||||||
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `TRAIT_REF_BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
|
|
||||||
|
|
|
||||||
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `<GlobalTraitRef as Foo>::BAR`...
|
= note: ...which requires normalizing `<GlobalTraitRef as Foo>::BAR`...
|
||||||
note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
|
note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
|
||||||
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
||||||
|
|
|
||||||
|
LL | const BAR: u32 = TRAIT_REF_BAR;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
||||||
|
|
|
|
||||||
LL | const BAR: u32 = TRAIT_REF_BAR;
|
LL | const BAR: u32 = TRAIT_REF_BAR;
|
||||||
|
@ -25,18 +30,13 @@ note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-a
|
||||||
|
|
|
|
||||||
LL | const BAR: u32 = TRAIT_REF_BAR;
|
LL | const BAR: u32 = TRAIT_REF_BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
|
||||||
|
|
|
||||||
LL | const BAR: u32 = TRAIT_REF_BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires optimizing MIR for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
|
note: ...which requires optimizing MIR for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
||||||
|
|
|
|
||||||
LL | const BAR: u32 = TRAIT_REF_BAR;
|
LL | const BAR: u32 = TRAIT_REF_BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `TRAIT_REF_BAR`...
|
= note: ...which requires normalizing `TRAIT_REF_BAR`...
|
||||||
= note: ...which again requires const-evaluating + checking `TRAIT_REF_BAR`, completing the cycle
|
= note: ...which again requires simplifying constant for the type system `TRAIT_REF_BAR`, completing the cycle
|
||||||
= note: cycle used when running analysis passes on this crate
|
= note: cycle used when running analysis passes on this crate
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
|
@ -9,9 +9,9 @@ LL | let x: &'static i32 = &(1 / 0);
|
||||||
= note: `#[deny(const_err)]` on by default
|
= note: `#[deny(const_err)]` on by default
|
||||||
|
|
||||||
query stack during panic:
|
query stack during panic:
|
||||||
#0 [const_eval_raw] const-evaluating `main::promoted[1]`
|
#0 [eval_to_allocation_raw] const-evaluating + checking `main::promoted[1]`
|
||||||
#1 [const_eval_validated] const-evaluating + checking `main::promoted[1]`
|
#1 [eval_to_const_value_raw] simplifying constant for the type system `main::promoted[1]`
|
||||||
#2 [const_eval_validated] const-evaluating + checking `main::promoted[1]`
|
#2 [eval_to_const_value_raw] simplifying constant for the type system `main::promoted[1]`
|
||||||
#3 [normalize_generic_arg_after_erasing_regions] normalizing `main::promoted[1]`
|
#3 [normalize_generic_arg_after_erasing_regions] normalizing `main::promoted[1]`
|
||||||
#4 [optimized_mir] optimizing MIR for `main`
|
#4 [optimized_mir] optimizing MIR for `main`
|
||||||
#5 [collect_and_partition_mono_items] collect_and_partition_mono_items
|
#5 [collect_and_partition_mono_items] collect_and_partition_mono_items
|
||||||
|
|
|
@ -36,7 +36,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const-pointer-values-in-various-types.rs:37:5
|
--> $DIR/const-pointer-values-in-various-types.rs:37:5
|
||||||
|
|
|
|
||||||
LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
|
LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc22, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc18, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= 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 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.
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const-pointer-values-in-various-types.rs:52:5
|
--> $DIR/const-pointer-values-in-various-types.rs:52:5
|
||||||
|
|
|
|
||||||
LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
|
LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc47, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc38, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= 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 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.
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const-pointer-values-in-various-types.rs:61:5
|
--> $DIR/const-pointer-values-in-various-types.rs:61:5
|
||||||
|
|
|
|
||||||
LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
|
LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc62, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc50, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= 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 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.
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const-pointer-values-in-various-types.rs:79:5
|
--> $DIR/const-pointer-values-in-various-types.rs:79:5
|
||||||
|
|
|
|
||||||
LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
|
LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc86, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc71, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= 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 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.
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const-pointer-values-in-various-types.rs:94:5
|
--> $DIR/const-pointer-values-in-various-types.rs:94:5
|
||||||
|
|
|
|
||||||
LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
|
LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc101, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc86, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= 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 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.
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/const-pointer-values-in-various-types.rs:103:5
|
--> $DIR/const-pointer-values-in-various-types.rs:103:5
|
||||||
|
|
|
|
||||||
LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
|
LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc110, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc95, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= 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 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.
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
// This test exhibits undefined behavior, but it is very expensive and complex to check for such
|
||||||
|
// UB in constants.
|
||||||
|
// Thus, we do not detect it if you create references to statics in ways that are UB.
|
||||||
|
|
||||||
enum Foo {
|
enum Foo {
|
||||||
A = 5,
|
A = 5,
|
||||||
B = 42,
|
B = 42,
|
||||||
|
@ -13,11 +19,14 @@ union Union {
|
||||||
u8: &'static u8,
|
u8: &'static u8,
|
||||||
}
|
}
|
||||||
static BAR: u8 = 5;
|
static BAR: u8 = 5;
|
||||||
static FOO: (&Foo, &Bar) = unsafe {( //~ undefined behavior
|
static FOO: (&Foo, &Bar) = unsafe {
|
||||||
Union { u8: &BAR }.foo,
|
(
|
||||||
Union { u8: &BAR }.bar,
|
// undefined behavior
|
||||||
)};
|
Union { u8: &BAR }.foo,
|
||||||
static FOO2: (&Foo, &Bar) = unsafe {(std::mem::transmute(&BAR), std::mem::transmute(&BAR))};
|
Union { u8: &BAR }.bar,
|
||||||
//~^ undefined behavior
|
)
|
||||||
|
};
|
||||||
|
static FOO2: (&Foo, &Bar) = unsafe { (std::mem::transmute(&BAR), std::mem::transmute(&BAR)) };
|
||||||
|
//^ undefined behavior
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
error[E0080]: it is undefined behavior to use this value
|
|
||||||
--> $DIR/double_check2.rs:16:1
|
|
||||||
|
|
|
||||||
LL | / static FOO: (&Foo, &Bar) = unsafe {(
|
|
||||||
LL | | Union { u8: &BAR }.foo,
|
|
||||||
LL | | Union { u8: &BAR }.bar,
|
|
||||||
LL | | )};
|
|
||||||
| |___^ type validation failed: encountered 0x05 at .1.<deref>.<enum-tag>, but expected a valid enum tag
|
|
||||||
|
|
|
||||||
= 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.
|
|
||||||
|
|
||||||
error[E0080]: it is undefined behavior to use this value
|
|
||||||
--> $DIR/double_check2.rs:20:1
|
|
||||||
|
|
|
||||||
LL | static FOO2: (&Foo, &Bar) = unsafe {(std::mem::transmute(&BAR), std::mem::transmute(&BAR))};
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x05 at .1.<deref>.<enum-tag>, but expected a valid enum tag
|
|
||||||
|
|
|
||||||
= 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.
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0080`.
|
|
|
@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-enum.rs:30:1
|
--> $DIR/ub-enum.rs:30:1
|
||||||
|
|
|
|
||||||
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc13 at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc12 at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= 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 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.
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-enum.rs:44:1
|
--> $DIR/ub-enum.rs:44:1
|
||||||
|
|
|
|
||||||
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc20 at .<enum-tag>, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc18 at .<enum-tag>, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= 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 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.
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-enum.rs:47:1
|
--> $DIR/ub-enum.rs:47:1
|
||||||
|
|
|
|
||||||
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc25 at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc22 at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= 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 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.
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-enum.rs:60:1
|
--> $DIR/ub-enum.rs:60:1
|
||||||
|
|
|
|
||||||
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc32 at .<enum-tag>, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc28 at .<enum-tag>, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= 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 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.
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
|
||||||
LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
|
LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
|
||||||
LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
|
LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
|
||||||
LL | | let out_of_bounds_ptr = &ptr[255];
|
LL | | let out_of_bounds_ptr = &ptr[255];
|
||||||
| | ^^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc11 which has size 1
|
| | ^^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
|
||||||
LL | | mem::transmute(out_of_bounds_ptr)
|
LL | | mem::transmute(out_of_bounds_ptr)
|
||||||
LL | | } };
|
LL | | } };
|
||||||
| |____-
|
| |____-
|
||||||
|
|
|
@ -34,7 +34,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-ref.rs:23:1
|
--> $DIR/ub-ref.rs:23:1
|
||||||
|
|
|
|
||||||
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
|
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc16, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc14, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= 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 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.
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0`
|
error[E0391]: cycle detected when simplifying constant for the type system `Foo::bytes::{{constant}}#0`
|
||||||
--> $DIR/const-size_of-cycle.rs:4:17
|
--> $DIR/const-size_of-cycle.rs:4:17
|
||||||
|
|
|
|
||||||
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
|
note: ...which requires simplifying constant for the type system `Foo::bytes::{{constant}}#0`...
|
||||||
|
--> $DIR/const-size_of-cycle.rs:4:17
|
||||||
|
|
|
||||||
|
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
|
note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
|
||||||
--> $DIR/const-size_of-cycle.rs:4:17
|
--> $DIR/const-size_of-cycle.rs:4:17
|
||||||
|
|
|
|
||||||
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
|
note: ...which requires const-evaluating + checking `std::mem::size_of`...
|
||||||
--> $DIR/const-size_of-cycle.rs:4:17
|
|
||||||
|
|
|
||||||
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `std::mem::size_of`...
|
|
||||||
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
||||||
|
|
|
|
||||||
LL | pub const fn size_of<T>() -> usize {
|
LL | pub const fn size_of<T>() -> usize {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
|
note: ...which requires simplifying constant for the type system `std::intrinsics::size_of`...
|
||||||
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
||||||
|
|
|
|
||||||
LL | pub fn size_of<T>() -> usize;
|
LL | pub fn size_of<T>() -> usize;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires computing layout of `Foo`...
|
= note: ...which requires computing layout of `Foo`...
|
||||||
= note: ...which requires normalizing `[u8; _]`...
|
= note: ...which requires normalizing `[u8; _]`...
|
||||||
= note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
|
= note: ...which again requires simplifying constant for the type system `Foo::bytes::{{constant}}#0`, completing the cycle
|
||||||
note: cycle used when checking that `Foo` is well-formed
|
note: cycle used when checking that `Foo` is well-formed
|
||||||
--> $DIR/const-size_of-cycle.rs:3:1
|
--> $DIR/const-size_of-cycle.rs:3:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
error[E0391]: cycle detected when const-evaluating `FOO`
|
error[E0391]: cycle detected when const-evaluating + checking `FOO`
|
||||||
--> $DIR/recursive-zst-static.rs:10:1
|
--> $DIR/recursive-zst-static.rs:10:1
|
||||||
|
|
|
|
||||||
LL | static FOO: () = FOO;
|
LL | static FOO: () = FOO;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires const-evaluating `FOO`...
|
note: ...which requires const-evaluating + checking `FOO`...
|
||||||
--> $DIR/recursive-zst-static.rs:10:1
|
|
||||||
|
|
|
||||||
LL | static FOO: () = FOO;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: ...which again requires const-evaluating `FOO`, completing the cycle
|
|
||||||
note: cycle used when const-evaluating + checking `FOO`
|
|
||||||
--> $DIR/recursive-zst-static.rs:10:1
|
--> $DIR/recursive-zst-static.rs:10:1
|
||||||
|
|
|
|
||||||
LL | static FOO: () = FOO;
|
LL | static FOO: () = FOO;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: ...which again requires const-evaluating + checking `FOO`, completing the cycle
|
||||||
|
= note: cycle used when running analysis passes on this crate
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
// can depend on this fact and will thus do unsound things when it is violated.
|
// can depend on this fact and will thus do unsound things when it is violated.
|
||||||
// See https://github.com/rust-lang/rust/issues/71078 for more details.
|
// See https://github.com/rust-lang/rust/issues/71078 for more details.
|
||||||
|
|
||||||
static FOO: () = FOO; //~ cycle detected when const-evaluating `FOO`
|
static FOO: () = FOO; //~ cycle detected when const-evaluating + checking `FOO`
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
FOO
|
FOO
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
error[E0391]: cycle detected when const-evaluating `FOO`
|
error[E0391]: cycle detected when const-evaluating + checking `FOO`
|
||||||
--> $DIR/recursive-zst-static.rs:10:1
|
--> $DIR/recursive-zst-static.rs:10:1
|
||||||
|
|
|
|
||||||
LL | static FOO: () = FOO;
|
LL | static FOO: () = FOO;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires const-evaluating `FOO`...
|
note: ...which requires const-evaluating + checking `FOO`...
|
||||||
--> $DIR/recursive-zst-static.rs:10:1
|
|
||||||
|
|
|
||||||
LL | static FOO: () = FOO;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: ...which again requires const-evaluating `FOO`, completing the cycle
|
|
||||||
note: cycle used when const-evaluating + checking `FOO`
|
|
||||||
--> $DIR/recursive-zst-static.rs:10:1
|
--> $DIR/recursive-zst-static.rs:10:1
|
||||||
|
|
|
|
||||||
LL | static FOO: () = FOO;
|
LL | static FOO: () = FOO;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: ...which again requires const-evaluating + checking `FOO`, completing the cycle
|
||||||
|
= note: cycle used when running analysis passes on this crate
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
//https://github.com/rust-lang/rust/issues/31364
|
//https://github.com/rust-lang/rust/issues/31364
|
||||||
|
|
||||||
const fn a() -> usize { b() } //~ ERROR cycle detected when const-evaluating `a` [E0391]
|
const fn a() -> usize {
|
||||||
const fn b() -> usize { a() }
|
//~^ ERROR cycle detected when const-evaluating + checking `a` [E0391]
|
||||||
|
b()
|
||||||
|
}
|
||||||
|
const fn b() -> usize {
|
||||||
|
a()
|
||||||
|
}
|
||||||
const ARR: [i32; a()] = [5; 6];
|
const ARR: [i32; a()] = [5; 6];
|
||||||
|
|
||||||
fn main(){}
|
fn main() {}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
error[E0391]: cycle detected when const-evaluating `a`
|
error[E0391]: cycle detected when const-evaluating + checking `a`
|
||||||
--> $DIR/infinite-recursion-const-fn.rs:3:1
|
--> $DIR/infinite-recursion-const-fn.rs:3:1
|
||||||
|
|
|
|
||||||
LL | const fn a() -> usize { b() }
|
LL | const fn a() -> usize {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires const-evaluating `b`...
|
note: ...which requires const-evaluating + checking `b`...
|
||||||
--> $DIR/infinite-recursion-const-fn.rs:4:1
|
--> $DIR/infinite-recursion-const-fn.rs:7:1
|
||||||
|
|
|
|
||||||
LL | const fn b() -> usize { a() }
|
LL | const fn b() -> usize {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which again requires const-evaluating `a`, completing the cycle
|
= note: ...which again requires const-evaluating + checking `a`, completing the cycle
|
||||||
note: cycle used when const-evaluating `ARR::{{constant}}#0`
|
note: cycle used when const-evaluating + checking `ARR::{{constant}}#0`
|
||||||
--> $DIR/infinite-recursion-const-fn.rs:5:18
|
--> $DIR/infinite-recursion-const-fn.rs:10:18
|
||||||
|
|
|
|
||||||
LL | const ARR: [i32; a()] = [5; 6];
|
LL | const ARR: [i32; a()] = [5; 6];
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
error[E0391]: cycle detected when normalizing `FOO`
|
error[E0391]: cycle detected when normalizing `FOO`
|
||||||
|
|
|
|
||||||
note: ...which requires const-evaluating + checking `FOO`...
|
note: ...which requires simplifying constant for the type system `FOO`...
|
||||||
|
--> $DIR/issue-17252.rs:1:1
|
||||||
|
|
|
||||||
|
LL | const FOO: usize = FOO;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires simplifying constant for the type system `FOO`...
|
||||||
--> $DIR/issue-17252.rs:1:1
|
--> $DIR/issue-17252.rs:1:1
|
||||||
|
|
|
|
||||||
LL | const FOO: usize = FOO;
|
LL | const FOO: usize = FOO;
|
||||||
|
@ -8,15 +13,10 @@ LL | const FOO: usize = FOO;
|
||||||
note: ...which requires const-evaluating + checking `FOO`...
|
note: ...which requires const-evaluating + checking `FOO`...
|
||||||
--> $DIR/issue-17252.rs:1:1
|
--> $DIR/issue-17252.rs:1:1
|
||||||
|
|
|
|
||||||
LL | const FOO: usize = FOO;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `FOO`...
|
|
||||||
--> $DIR/issue-17252.rs:1:1
|
|
||||||
|
|
|
||||||
LL | const FOO: usize = FOO;
|
LL | const FOO: usize = FOO;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which again requires normalizing `FOO`, completing the cycle
|
= note: ...which again requires normalizing `FOO`, completing the cycle
|
||||||
note: cycle used when const-evaluating `main::{{constant}}#0`
|
note: cycle used when const-evaluating + checking `main::{{constant}}#0`
|
||||||
--> $DIR/issue-17252.rs:4:18
|
--> $DIR/issue-17252.rs:4:18
|
||||||
|
|
|
|
||||||
LL | let _x: [u8; FOO]; // caused stack overflow prior to fix
|
LL | let _x: [u8; FOO]; // caused stack overflow prior to fix
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
error[E0391]: cycle detected when const-evaluating + checking `X::A::{{constant}}#0`
|
error[E0391]: cycle detected when simplifying constant for the type system `X::A::{{constant}}#0`
|
||||||
--> $DIR/issue-23302-1.rs:4:9
|
--> $DIR/issue-23302-1.rs:4:9
|
||||||
|
|
|
|
||||||
LL | A = X::A as isize,
|
LL | A = X::A as isize,
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
|
note: ...which requires simplifying constant for the type system `X::A::{{constant}}#0`...
|
||||||
|
--> $DIR/issue-23302-1.rs:4:9
|
||||||
|
|
|
||||||
|
LL | A = X::A as isize,
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `X::A::{{constant}}#0`...
|
note: ...which requires const-evaluating + checking `X::A::{{constant}}#0`...
|
||||||
--> $DIR/issue-23302-1.rs:4:9
|
--> $DIR/issue-23302-1.rs:4:9
|
||||||
|
|
|
|
||||||
LL | A = X::A as isize,
|
|
||||||
| ^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `X::A::{{constant}}#0`...
|
|
||||||
--> $DIR/issue-23302-1.rs:4:9
|
|
||||||
|
|
|
||||||
LL | A = X::A as isize,
|
LL | A = X::A as isize,
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `X::A as isize`...
|
= note: ...which requires normalizing `X::A as isize`...
|
||||||
= note: ...which again requires const-evaluating + checking `X::A::{{constant}}#0`, completing the cycle
|
= note: ...which again requires simplifying constant for the type system `X::A::{{constant}}#0`, completing the cycle
|
||||||
note: cycle used when collecting item types in top-level module
|
note: cycle used when collecting item types in top-level module
|
||||||
--> $DIR/issue-23302-1.rs:3:1
|
--> $DIR/issue-23302-1.rs:3:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
error[E0391]: cycle detected when const-evaluating + checking `Y::A::{{constant}}#0`
|
error[E0391]: cycle detected when simplifying constant for the type system `Y::A::{{constant}}#0`
|
||||||
--> $DIR/issue-23302-2.rs:4:9
|
--> $DIR/issue-23302-2.rs:4:9
|
||||||
|
|
|
|
||||||
LL | A = Y::B as isize,
|
LL | A = Y::B as isize,
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
|
note: ...which requires simplifying constant for the type system `Y::A::{{constant}}#0`...
|
||||||
|
--> $DIR/issue-23302-2.rs:4:9
|
||||||
|
|
|
||||||
|
LL | A = Y::B as isize,
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `Y::A::{{constant}}#0`...
|
note: ...which requires const-evaluating + checking `Y::A::{{constant}}#0`...
|
||||||
--> $DIR/issue-23302-2.rs:4:9
|
--> $DIR/issue-23302-2.rs:4:9
|
||||||
|
|
|
|
||||||
LL | A = Y::B as isize,
|
|
||||||
| ^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `Y::A::{{constant}}#0`...
|
|
||||||
--> $DIR/issue-23302-2.rs:4:9
|
|
||||||
|
|
|
||||||
LL | A = Y::B as isize,
|
LL | A = Y::B as isize,
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `Y::B as isize`...
|
= note: ...which requires normalizing `Y::B as isize`...
|
||||||
= note: ...which again requires const-evaluating + checking `Y::A::{{constant}}#0`, completing the cycle
|
= note: ...which again requires simplifying constant for the type system `Y::A::{{constant}}#0`, completing the cycle
|
||||||
note: cycle used when collecting item types in top-level module
|
note: cycle used when collecting item types in top-level module
|
||||||
--> $DIR/issue-23302-2.rs:3:1
|
--> $DIR/issue-23302-2.rs:3:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,21 +1,26 @@
|
||||||
error[E0391]: cycle detected when const-evaluating + checking `A`
|
error[E0391]: cycle detected when simplifying constant for the type system `A`
|
||||||
--> $DIR/issue-23302-3.rs:1:1
|
--> $DIR/issue-23302-3.rs:1:1
|
||||||
|
|
|
|
||||||
LL | const A: i32 = B;
|
LL | const A: i32 = B;
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
|
note: ...which requires simplifying constant for the type system `A`...
|
||||||
|
--> $DIR/issue-23302-3.rs:1:1
|
||||||
|
|
|
||||||
|
LL | const A: i32 = B;
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `A`...
|
note: ...which requires const-evaluating + checking `A`...
|
||||||
--> $DIR/issue-23302-3.rs:1:1
|
--> $DIR/issue-23302-3.rs:1:1
|
||||||
|
|
|
|
||||||
LL | const A: i32 = B;
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `A`...
|
|
||||||
--> $DIR/issue-23302-3.rs:1:1
|
|
||||||
|
|
|
||||||
LL | const A: i32 = B;
|
LL | const A: i32 = B;
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `B`...
|
= note: ...which requires normalizing `B`...
|
||||||
note: ...which requires const-evaluating + checking `B`...
|
note: ...which requires simplifying constant for the type system `B`...
|
||||||
|
--> $DIR/issue-23302-3.rs:3:1
|
||||||
|
|
|
||||||
|
LL | const B: i32 = A;
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires simplifying constant for the type system `B`...
|
||||||
--> $DIR/issue-23302-3.rs:3:1
|
--> $DIR/issue-23302-3.rs:3:1
|
||||||
|
|
|
|
||||||
LL | const B: i32 = A;
|
LL | const B: i32 = A;
|
||||||
|
@ -23,15 +28,10 @@ LL | const B: i32 = A;
|
||||||
note: ...which requires const-evaluating + checking `B`...
|
note: ...which requires const-evaluating + checking `B`...
|
||||||
--> $DIR/issue-23302-3.rs:3:1
|
--> $DIR/issue-23302-3.rs:3:1
|
||||||
|
|
|
|
||||||
LL | const B: i32 = A;
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `B`...
|
|
||||||
--> $DIR/issue-23302-3.rs:3:1
|
|
||||||
|
|
|
||||||
LL | const B: i32 = A;
|
LL | const B: i32 = A;
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `A`...
|
= note: ...which requires normalizing `A`...
|
||||||
= note: ...which again requires const-evaluating + checking `A`, completing the cycle
|
= note: ...which again requires simplifying constant for the type system `A`, completing the cycle
|
||||||
= note: cycle used when running analysis passes on this crate
|
= note: cycle used when running analysis passes on this crate
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
|
@ -1,21 +1,26 @@
|
||||||
error[E0391]: cycle detected when const-evaluating + checking `Foo::B::{{constant}}#0`
|
error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{{constant}}#0`
|
||||||
--> $DIR/issue-36163.rs:4:9
|
--> $DIR/issue-36163.rs:4:9
|
||||||
|
|
|
|
||||||
LL | B = A,
|
LL | B = A,
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
|
note: ...which requires simplifying constant for the type system `Foo::B::{{constant}}#0`...
|
||||||
|
--> $DIR/issue-36163.rs:4:9
|
||||||
|
|
|
||||||
|
LL | B = A,
|
||||||
|
| ^
|
||||||
note: ...which requires const-evaluating + checking `Foo::B::{{constant}}#0`...
|
note: ...which requires const-evaluating + checking `Foo::B::{{constant}}#0`...
|
||||||
--> $DIR/issue-36163.rs:4:9
|
--> $DIR/issue-36163.rs:4:9
|
||||||
|
|
|
|
||||||
LL | B = A,
|
|
||||||
| ^
|
|
||||||
note: ...which requires const-evaluating `Foo::B::{{constant}}#0`...
|
|
||||||
--> $DIR/issue-36163.rs:4:9
|
|
||||||
|
|
|
||||||
LL | B = A,
|
LL | B = A,
|
||||||
| ^
|
| ^
|
||||||
= note: ...which requires normalizing `A`...
|
= note: ...which requires normalizing `A`...
|
||||||
note: ...which requires const-evaluating + checking `A`...
|
note: ...which requires simplifying constant for the type system `A`...
|
||||||
|
--> $DIR/issue-36163.rs:1:1
|
||||||
|
|
|
||||||
|
LL | const A: isize = Foo::B as isize;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires simplifying constant for the type system `A`...
|
||||||
--> $DIR/issue-36163.rs:1:1
|
--> $DIR/issue-36163.rs:1:1
|
||||||
|
|
|
|
||||||
LL | const A: isize = Foo::B as isize;
|
LL | const A: isize = Foo::B as isize;
|
||||||
|
@ -23,15 +28,10 @@ LL | const A: isize = Foo::B as isize;
|
||||||
note: ...which requires const-evaluating + checking `A`...
|
note: ...which requires const-evaluating + checking `A`...
|
||||||
--> $DIR/issue-36163.rs:1:1
|
--> $DIR/issue-36163.rs:1:1
|
||||||
|
|
|
|
||||||
LL | const A: isize = Foo::B as isize;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `A`...
|
|
||||||
--> $DIR/issue-36163.rs:1:1
|
|
||||||
|
|
|
||||||
LL | const A: isize = Foo::B as isize;
|
LL | const A: isize = Foo::B as isize;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `A`...
|
= note: ...which requires normalizing `A`...
|
||||||
= note: ...which again requires const-evaluating + checking `Foo::B::{{constant}}#0`, completing the cycle
|
= note: ...which again requires simplifying constant for the type system `Foo::B::{{constant}}#0`, completing the cycle
|
||||||
note: cycle used when collecting item types in top-level module
|
note: cycle used when collecting item types in top-level module
|
||||||
--> $DIR/issue-36163.rs:1:1
|
--> $DIR/issue-36163.rs:1:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub static FOO: u32 = FOO;
|
pub static FOO: u32 = FOO;
|
||||||
//~^ ERROR cycle detected when const-evaluating `FOO`
|
//~^ ERROR cycle detected when const-evaluating + checking `FOO`
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
error[E0391]: cycle detected when const-evaluating `FOO`
|
error[E0391]: cycle detected when const-evaluating + checking `FOO`
|
||||||
--> $DIR/recursive-static-definition.rs:1:1
|
--> $DIR/recursive-static-definition.rs:1:1
|
||||||
|
|
|
|
||||||
LL | pub static FOO: u32 = FOO;
|
LL | pub static FOO: u32 = FOO;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires const-evaluating `FOO`...
|
note: ...which requires const-evaluating + checking `FOO`...
|
||||||
--> $DIR/recursive-static-definition.rs:1:1
|
|
||||||
|
|
|
||||||
LL | pub static FOO: u32 = FOO;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: ...which again requires const-evaluating `FOO`, completing the cycle
|
|
||||||
note: cycle used when const-evaluating + checking `FOO`
|
|
||||||
--> $DIR/recursive-static-definition.rs:1:1
|
--> $DIR/recursive-static-definition.rs:1:1
|
||||||
|
|
|
|
||||||
LL | pub static FOO: u32 = FOO;
|
LL | pub static FOO: u32 = FOO;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: ...which again requires const-evaluating + checking `FOO`, completing the cycle
|
||||||
|
= note: cycle used when running analysis passes on this crate
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
enum Alpha {
|
enum Alpha {
|
||||||
V1 = 41,
|
V1 = 41,
|
||||||
V2 = Self::V1 as u8 + 1, // OK; See #50072.
|
V2 = Self::V1 as u8 + 1, // OK; See #50072.
|
||||||
V3 = Self::V1 {} as u8 + 2, //~ ERROR cycle detected when const-evaluating
|
V3 = Self::V1 {} as u8 + 2, //~ ERROR cycle detected when simplifying constant
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
error[E0391]: cycle detected when const-evaluating + checking `Alpha::V3::{{constant}}#0`
|
error[E0391]: cycle detected when simplifying constant for the type system `Alpha::V3::{{constant}}#0`
|
||||||
--> $DIR/self-in-enum-definition.rs:5:10
|
--> $DIR/self-in-enum-definition.rs:5:10
|
||||||
|
|
|
|
||||||
LL | V3 = Self::V1 {} as u8 + 2,
|
LL | V3 = Self::V1 {} as u8 + 2,
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
|
note: ...which requires simplifying constant for the type system `Alpha::V3::{{constant}}#0`...
|
||||||
|
--> $DIR/self-in-enum-definition.rs:5:10
|
||||||
|
|
|
||||||
|
LL | V3 = Self::V1 {} as u8 + 2,
|
||||||
|
| ^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `Alpha::V3::{{constant}}#0`...
|
note: ...which requires const-evaluating + checking `Alpha::V3::{{constant}}#0`...
|
||||||
--> $DIR/self-in-enum-definition.rs:5:10
|
--> $DIR/self-in-enum-definition.rs:5:10
|
||||||
|
|
|
|
||||||
LL | V3 = Self::V1 {} as u8 + 2,
|
|
||||||
| ^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating `Alpha::V3::{{constant}}#0`...
|
|
||||||
--> $DIR/self-in-enum-definition.rs:5:10
|
|
||||||
|
|
|
||||||
LL | V3 = Self::V1 {} as u8 + 2,
|
LL | V3 = Self::V1 {} as u8 + 2,
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
= note: ...which requires computing layout of `Alpha`...
|
= note: ...which requires computing layout of `Alpha`...
|
||||||
= note: ...which again requires const-evaluating + checking `Alpha::V3::{{constant}}#0`, completing the cycle
|
= note: ...which again requires simplifying constant for the type system `Alpha::V3::{{constant}}#0`, completing the cycle
|
||||||
note: cycle used when collecting item types in top-level module
|
note: cycle used when collecting item types in top-level module
|
||||||
--> $DIR/self-in-enum-definition.rs:1:1
|
--> $DIR/self-in-enum-definition.rs:1:1
|
||||||
|
|
|
|
||||||
LL | / #[repr(u8)]
|
LL | / #[repr(u8)]
|
||||||
LL | | enum Alpha {
|
LL | | enum Alpha {
|
||||||
LL | | V1 = 41,
|
LL | | V1 = 41,
|
||||||
LL | | V2 = Self::V1 as u8 + 1, // OK; See #50072.
|
LL | | V2 = Self::V1 as u8 + 1, // OK; See #50072.
|
||||||
... |
|
... |
|
||||||
LL | |
|
LL | |
|
||||||
LL | | fn main() {}
|
LL | | fn main() {}
|
||||||
|
|
|
@ -4,23 +4,19 @@ error[E0080]: could not evaluate static initializer
|
||||||
LL | pub static mut B: () = unsafe { A = 1; };
|
LL | pub static mut B: () = unsafe { A = 1; };
|
||||||
| ^^^^^ modifying a static's initial value from another static's initializer
|
| ^^^^^ modifying a static's initial value from another static's initializer
|
||||||
|
|
||||||
error[E0391]: cycle detected when const-evaluating `C`
|
error[E0391]: cycle detected when const-evaluating + checking `C`
|
||||||
--> $DIR/write-to-static-mut-in-static.rs:5:1
|
--> $DIR/write-to-static-mut-in-static.rs:5:1
|
||||||
|
|
|
|
||||||
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
|
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires const-evaluating `C`...
|
note: ...which requires const-evaluating + checking `C`...
|
||||||
--> $DIR/write-to-static-mut-in-static.rs:5:1
|
|
||||||
|
|
|
||||||
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: ...which again requires const-evaluating `C`, completing the cycle
|
|
||||||
note: cycle used when const-evaluating + checking `C`
|
|
||||||
--> $DIR/write-to-static-mut-in-static.rs:5:1
|
--> $DIR/write-to-static-mut-in-static.rs:5:1
|
||||||
|
|
|
|
||||||
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
|
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: ...which again requires const-evaluating + checking `C`, completing the cycle
|
||||||
|
= note: cycle used when running analysis passes on this crate
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue