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:
bors 2020-09-20 08:58:32 +00:00
commit 5e449b9adf
52 changed files with 347 additions and 420 deletions

View File

@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::Node;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
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::ty::{self, Instance, Ty};
@ -85,10 +85,7 @@ pub fn codegen_static_initializer(
cx: &CodegenCx<'ll, 'tcx>,
def_id: DefId,
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
let alloc = match cx.tcx.const_eval_poly(def_id)? {
ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => alloc,
val => bug!("static const eval returned {:#?}", val),
};
let alloc = cx.tcx.eval_static_initializer(def_id)?;
Ok((const_alloc_to_llvm(cx, alloc), alloc))
}

View File

@ -13,7 +13,7 @@ use rustc_ast as ast;
use rustc_hir::lang_items::LangItem;
use rustc_index::vec::Idx;
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::ty::layout::{FnAbiExt, HasTyCtxt};
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 size = bx.layout_of(ty).size;
let scalar = match const_value {
// Promoted constants are evaluated into a ByRef instead of a Scalar,
// but we want the scalar value here.
ConstValue::ByRef { alloc, offset } => {
let ptr = Pointer::new(AllocId(0), offset);
alloc
.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"),
ConstValue::Scalar(s) => s,
_ => span_bug!(
span,
"expected Scalar for promoted asm const, but got {:#?}",
const_value
),
};
let value = scalar.assert_bits(size);
let string = match ty.kind() {

View File

@ -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::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
use rustc_middle::mir;
use rustc_middle::mir::interpret::ConstEvalResult;
use rustc_middle::mir::interpret::EvalToConstValueResult;
use rustc_middle::traits::select;
use rustc_middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
@ -1542,7 +1542,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
substs: SubstsRef<'tcx>,
promoted: Option<mir::Promoted>,
span: Option<Span>,
) -> ConstEvalResult<'tcx> {
) -> EvalToConstValueResult<'tcx> {
let mut original_values = OriginalQueryValues::default();
let canonical = self.canonicalize_query(&(param_env, substs), &mut original_values);

View File

@ -1474,21 +1474,19 @@ declare_lint_pass!(
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 {
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
match it.kind {
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) => {
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);
}
_ => {}
}

View File

@ -1,4 +1,4 @@
use super::{AllocId, Pointer, RawConst, Scalar};
use super::{AllocId, ConstAlloc, Pointer, Scalar};
use crate::mir::interpret::ConstValue;
use crate::ty::{layout, query::TyCtxtAt, tls, FnSig, Ty};
@ -27,8 +27,8 @@ CloneTypeFoldableAndLiftImpls! {
ErrorHandled,
}
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
pub type ConstEvalResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'tcx> {
struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)

View File

@ -118,12 +118,12 @@ use crate::ty::subst::GenericArgKind;
use crate::ty::{self, Instance, Ty, TyCtxt};
pub use self::error::{
struct_error, CheckInAllocMsg, ConstEvalRawResult, ConstEvalResult, ErrorHandled, InterpError,
InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType, ResourceExhaustionInfo,
UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType,
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};

View File

@ -1,4 +1,4 @@
use super::{ConstEvalResult, ErrorHandled, GlobalId};
use super::{ErrorHandled, EvalToConstValueResult, GlobalId};
use crate::mir;
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
/// 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.
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
// 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
@ -38,7 +38,7 @@ impl<'tcx> TyCtxt<'tcx> {
substs: SubstsRef<'tcx>,
promoted: Option<mir::Promoted>,
span: Option<Span>,
) -> ConstEvalResult<'tcx> {
) -> EvalToConstValueResult<'tcx> {
match ty::Instance::resolve_opt_const_arg(self, param_env, def, substs) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted };
@ -54,7 +54,7 @@ impl<'tcx> TyCtxt<'tcx> {
param_env: ty::ParamEnv<'tcx>,
instance: ty::Instance<'tcx>,
span: Option<Span>,
) -> ConstEvalResult<'tcx> {
) -> EvalToConstValueResult<'tcx> {
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>,
cid: GlobalId<'tcx>,
span: Option<Span>,
) -> ConstEvalResult<'tcx> {
) -> EvalToConstValueResult<'tcx> {
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
// improve caching of queries.
let inputs = self.erase_regions(&param_env.and(cid));
if let Some(span) = span {
self.at(span).const_eval_validated(inputs)
self.at(span).eval_to_const_value_raw(inputs)
} 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>,
) -> Result<&'tcx mir::Allocation, ErrorHandled> {
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())
}
}

View File

@ -12,9 +12,9 @@ use crate::ty::{ParamEnv, Ty, TyCtxt};
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)]
pub struct RawConst<'tcx> {
pub struct ConstAlloc<'tcx> {
// the value lives here, at offset 0, and that allocation definitely is a `AllocKind::Memory`
// (so you can use `AllocMap::unwrap_memory`).
pub alloc_id: AllocId,

View File

@ -707,32 +707,27 @@ rustc_queries! {
}
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
/// during validation. Please add a comment to every use site explaining why using
/// `const_eval_validated` isn't sufficient. The returned constant also isn't in a suitable
/// form to be used outside of const eval.
query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-> ConstEvalRawResult<'tcx> {
/// **Do not use this** directly, use the `tcx.eval_static_initializer` wrapper.
query eval_to_allocation_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-> EvalToAllocationRawResult<'tcx> {
desc { |tcx|
"const-evaluating `{}`",
"const-evaluating + checking `{}`",
key.value.display(tcx)
}
}
/// Results of evaluating const items or constants embedded in
/// other items (such as enum variant explicit discriminants).
///
/// 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.
/// Evaluates const items or anonymous constants
/// (such as enum variant explicit discriminants or array lengths)
/// into a representation suitable for the type system and const generics.
///
/// **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`.
query const_eval_validated(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-> ConstEvalResult<'tcx> {
query eval_to_const_value_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-> EvalToConstValueResult<'tcx> {
desc { |tcx|
"const-evaluating + checking `{}`",
"simplifying constant for the type system `{}`",
key.value.display(tcx)
}
cache_on_disk_if(_, opt_result) {

View File

@ -14,7 +14,7 @@ use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLife
use crate::middle::stability::{self, DeprecationEntry};
use crate::mir;
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::mono::CodegenUnit;
use crate::traits::query::{

View File

@ -1,8 +1,8 @@
use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr, MemoryExtra};
use crate::interpret::eval_nullary_intrinsic;
use crate::interpret::{
intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, Immediate, InternKind,
InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar,
intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, GlobalId, Immediate,
InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, Scalar,
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>(
ecx: &CompileTimeEvalContext<'_, '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>,
constant: RawConst<'tcx>,
constant: ConstAlloc<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::ConstEvalResult<'tcx> {
) -> ConstValue<'tcx> {
let cid = key.value;
let def_id = cid.instance.def.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 val = (|| {
let mplace = ecx.raw_const_to_mplace(constant)?;
// 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,
)?;
}
}
// 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();
})
})
let mplace = ecx.raw_const_to_mplace(constant).expect(
"can only fail if layout computation failed, \
which should have given a good error before ever invoking this function",
);
assert!(
!is_static || cid.promoted.is_some(),
"the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
);
// Turn this into a proper constant.
op_to_const(&ecx, mplace.into())
}
pub fn const_eval_validated_provider<'tcx>(
pub fn eval_to_const_value_raw_provider<'tcx>(
tcx: TyCtxt<'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
if key.param_env.reveal() == Reveal::All {
let mut key = key;
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
Err(ErrorHandled::TooGeneric) => {}
// 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>,
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
// 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
@ -279,7 +255,7 @@ pub fn const_eval_raw_provider<'tcx>(
if key.param_env.reveal() == Reveal::All {
let mut key = key;
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
Err(ErrorHandled::TooGeneric) => {}
// deduplicate calls
@ -318,9 +294,8 @@ pub fn const_eval_raw_provider<'tcx>(
);
let res = ecx.load_mir(cid.instance.def, cid.promoted);
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 })
.map_err(|error| {
match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) {
Err(error) => {
let err = ConstEvalErr::new(&ecx, error, None);
// errors in statics are always emitted as fatal errors
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() {
// constant defined in this crate, we can figure out a lint level!
match tcx.def_kind(def.did.to_def_id()) {
@ -356,12 +331,12 @@ pub fn const_eval_raw_provider<'tcx>(
// compatibility hazard
DefKind::Const | DefKind::AssocConst => {
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)),
"any use of this value will cause an error",
hir_id,
Some(err.span),
)
))
}
// 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
@ -370,31 +345,65 @@ pub fn const_eval_raw_provider<'tcx>(
if let Some(p) = cid.promoted {
let span = tcx.promoted_mir_of_opt_const_arg(def.to_global())[p].span;
if let err_inval!(ReferencedConstant) = err.error {
err.report_as_error(
Err(err.report_as_error(
tcx.at(span),
"evaluation of constant expression failed",
)
))
} else {
err.report_as_lint(
Err(err.report_as_lint(
tcx.at(span),
"reaching this expression at runtime will panic or abort",
tcx.hir().local_def_id_to_hir_id(def.did),
Some(err.span),
)
))
}
// anything else (array lengths, enum initializers, constant patterns) are
// reported as hard errors
} else {
err.report_as_error(
Err(err.report_as_error(
ecx.tcx.at(ecx.cur_span()),
"evaluation of constant value failed",
)
))
}
}
}
} else {
// 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 })
}
}
}
}

View File

@ -51,7 +51,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
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)?;

View File

@ -20,7 +20,7 @@ use rustc_span::{Pos, Span};
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
use super::{
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, Operand, Place, PlaceTy,
ScalarMaybeUninit, StackPopJump,
};
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(())
}
pub(super) fn const_eval(
&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(
pub fn eval_to_allocation(
&self,
gid: GlobalId<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
@ -914,14 +889,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} else {
self.param_env
};
// We use `const_eval_raw` here, and get an unvalidated result. That is okay:
// 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))?;
let val = self.tcx.eval_to_allocation_raw(param_env.and(gid))?;
self.raw_const_to_mplace(val)
}

View File

@ -152,7 +152,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
sym::type_name => self.tcx.mk_static_str(),
_ => 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)?;
}

View File

@ -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
// 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
// `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.
// 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!

View File

@ -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::Unevaluated(def, substs, promoted) => {
let instance = self.resolve(def.did, substs)?;
// We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation.
// 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)?);
return Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into());
}
ty::ConstKind::Infer(..)
| ty::ConstKind::Bound(..)

View File

@ -13,9 +13,9 @@ use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
use super::{
mir_assign_valid_types, truncate, AllocId, AllocMap, Allocation, AllocationExtra, ImmTy,
Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer,
PointerArithmetic, RawConst, Scalar, ScalarMaybeUninit,
mir_assign_valid_types, truncate, AllocId, AllocMap, Allocation, AllocationExtra, ConstAlloc,
ImmTy, Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand,
Pointer, PointerArithmetic, Scalar, ScalarMaybeUninit,
};
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
@ -1120,7 +1120,7 @@ where
pub fn raw_const_to_mplace(
&self,
raw: RawConst<'tcx>,
raw: ConstAlloc<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
// This must be an allocation in `tcx`
let _ = self.tcx.global_alloc(raw.alloc_id);

View File

@ -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);
if let Some(GlobalAlloc::Static(did)) = alloc_kind {
assert!(!self.ecx.tcx.is_thread_local_static(did));
// 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`).
// We also need to do it here instead of going on to avoid running
// into the `before_access_global` check during validation.
if !self.may_ref_to_static && self.ecx.tcx.is_static(did) {
assert!(self.ecx.tcx.is_static(did));
if self.may_ref_to_static {
// We skip checking other statics. These statics must be sound by
// themselves, and the only way to get broken statics here is by using
// unsafe code.
// The reasons we don't check other statics is twofold. For one, in all
// 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,
{ "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!

View File

@ -53,8 +53,8 @@ pub fn provide(providers: &mut Providers) {
transform::provide(providers);
monomorphize::partitioning::provide(providers);
monomorphize::polymorphize::provide(providers);
providers.const_eval_validated = const_eval::const_eval_validated_provider;
providers.const_eval_raw = const_eval::const_eval_raw_provider;
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
providers.const_caller_location = const_eval::const_caller_location;
providers.destructure_const = |tcx, param_env_and_value| {
let (param_env, value) = param_env_and_value.into_parts();

View File

@ -364,8 +364,10 @@ fn collect_items_rec<'tcx>(
recursion_depth_reset = None;
if let Ok(val) = tcx.const_eval_poly(def_id) {
collect_const_value(tcx, val, &mut neighbors);
if let Ok(alloc) = tcx.eval_static_initializer(def_id) {
for &((), id) in alloc.relocations().values() {
collect_miri(tcx, id, &mut neighbors);
}
}
}
MonoItem::Fn(instance) => {

View File

@ -631,14 +631,11 @@ pub fn write_allocations<'tcx>(
None => write!(w, " (deallocated)")?,
Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {})", inst)?,
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
match tcx.const_eval_poly(did) {
Ok(ConstValue::ByRef { alloc, .. }) => {
match tcx.eval_static_initializer(did) {
Ok(alloc) => {
write!(w, " (static: {}, ", tcx.def_path_str(did))?;
write_allocation_track_relocs(w, alloc)?;
}
Ok(_) => {
span_bug!(tcx.def_span(did), " static item without `ByRef` initializer")
}
Err(_) => write!(
w,
" (static: {}, error during initializer evaluation)",

View File

@ -111,7 +111,6 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_infer::infer::{InferCtxt, InferOk, InferResult, RegionVariableOrigin, TyCtxtInferExt};
use rustc_middle::hir::map::blocks::FnLikeNode;
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty::adjustment::{
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
// the consumer's responsibility to ensure all bytes that have been read
// have defined values.
match tcx.const_eval_poly(id.to_def_id()) {
Ok(ConstValue::ByRef { alloc, .. }) => {
match tcx.eval_static_initializer(id.to_def_id()) {
Ok(alloc) => {
if alloc.relocations().len() != 0 {
let msg = "statics with a custom `#[link_section]` must be a \
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);
}
}
Ok(_) => bug!("Matching on non-ByRef static"),
Err(_) => {}
}
}

View File

@ -14,7 +14,7 @@
// 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
// 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)]
// 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]
pub fn low_align_const() -> E<i16, [i16; 3]> {
// 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)
}
@ -51,6 +51,6 @@ pub fn low_align_const() -> E<i16, [i16; 3]> {
#[no_mangle]
pub fn high_align_const() -> E<i16, i32> {
// 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)
}

View File

@ -4,7 +4,7 @@ use std::intrinsics;
struct 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,
}

View File

@ -11,7 +11,7 @@ impl Tr for str {
type Arr = [u8; 8];
#[cfg(cfail)]
type Arr = [u8; Self::C];
//[cfail]~^ ERROR cycle detected when const-evaluating
//[cfail]~^ ERROR cycle detected when simplifying constant
}
fn main() {}

View File

@ -1,6 +1,11 @@
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
|
LL | const A: u8 = Self::B;
@ -8,15 +13,15 @@ LL | const A: u8 = Self::B;
note: ...which requires const-evaluating + checking `Tr::A`...
--> $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;
| ^^^^^^^^^^^^^^^^^^^^^^
= 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
|
LL | const B: u8 = Self::A;
@ -24,15 +29,10 @@ LL | const B: u8 = Self::A;
note: ...which requires const-evaluating + checking `Tr::B`...
--> $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;
| ^^^^^^^^^^^^^^^^^^^^^^
= 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
|
LL | fn main() {

View File

@ -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
|
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`...
--> $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;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
|
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;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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`...
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
LL | const BAR: u32 = 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
error: aborting due to previous error

View File

@ -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
|
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`...
--> $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;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
|
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;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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`...
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
LL | const BAR: u32 = 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
error: aborting due to previous error

View File

@ -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
|
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`...
--> $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;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
|
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;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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`...
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
LL | const BAR: u32 = 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
error: aborting due to previous error

View File

@ -9,9 +9,9 @@ LL | let x: &'static i32 = &(1 / 0);
= note: `#[deny(const_err)]` on by default
query stack during panic:
#0 [const_eval_raw] const-evaluating `main::promoted[1]`
#1 [const_eval_validated] const-evaluating + checking `main::promoted[1]`
#2 [const_eval_validated] const-evaluating + checking `main::promoted[1]`
#0 [eval_to_allocation_raw] const-evaluating + checking `main::promoted[1]`
#1 [eval_to_const_value_raw] simplifying constant for the type system `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]`
#4 [optimized_mir] optimizing MIR for `main`
#5 [collect_and_partition_mono_items] collect_and_partition_mono_items

View File

@ -36,7 +36,7 @@ error[E0080]: it is undefined behavior to use this value
--> $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 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
@ -76,7 +76,7 @@ error[E0080]: it is undefined behavior to use this value
--> $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 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
@ -100,7 +100,7 @@ error[E0080]: it is undefined behavior to use this value
--> $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 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
@ -148,7 +148,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/const-pointer-values-in-various-types.rs:79:5
|
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.
@ -188,7 +188,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/const-pointer-values-in-various-types.rs:94:5
|
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.
@ -212,7 +212,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/const-pointer-values-in-various-types.rs:103:5
|
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.

View File

@ -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 {
A = 5,
B = 42,
@ -13,11 +19,14 @@ union Union {
u8: &'static u8,
}
static BAR: u8 = 5;
static FOO: (&Foo, &Bar) = unsafe {( //~ undefined behavior
Union { u8: &BAR }.foo,
Union { u8: &BAR }.bar,
)};
static FOO2: (&Foo, &Bar) = unsafe {(std::mem::transmute(&BAR), std::mem::transmute(&BAR))};
//~^ undefined behavior
static FOO: (&Foo, &Bar) = unsafe {
(
// undefined behavior
Union { u8: &BAR }.foo,
Union { u8: &BAR }.bar,
)
};
static FOO2: (&Foo, &Bar) = unsafe { (std::mem::transmute(&BAR), std::mem::transmute(&BAR)) };
//^ undefined behavior
fn main() {}

View File

@ -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`.

View File

@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:30: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.
@ -34,7 +34,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:44:1
|
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.
@ -42,7 +42,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:47:1
|
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.
@ -58,7 +58,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:60:1
|
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.

View File

@ -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 | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
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 | | } };
| |____-

View File

@ -34,7 +34,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-ref.rs:23:1
|
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.

View File

@ -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
|
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`...
--> $DIR/const-size_of-cycle.rs:4:17
|
LL | bytes: [u8; std::mem::size_of::<Foo>()]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating `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 `std::mem::size_of`...
note: ...which requires const-evaluating + checking `std::mem::size_of`...
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
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
|
LL | pub fn size_of<T>() -> usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing layout of `Foo`...
= 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
--> $DIR/const-size_of-cycle.rs:3:1
|

View File

@ -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
|
LL | static FOO: () = FOO;
| ^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `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`
note: ...which requires const-evaluating + checking `FOO`...
--> $DIR/recursive-zst-static.rs:10:1
|
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

View File

@ -7,7 +7,7 @@
// 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.
static FOO: () = FOO; //~ cycle detected when const-evaluating `FOO`
static FOO: () = FOO; //~ cycle detected when const-evaluating + checking `FOO`
fn main() {
FOO

View File

@ -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
|
LL | static FOO: () = FOO;
| ^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `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`
note: ...which requires const-evaluating + checking `FOO`...
--> $DIR/recursive-zst-static.rs:10:1
|
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

View File

@ -1,7 +1,12 @@
//https://github.com/rust-lang/rust/issues/31364
const fn a() -> usize { b() } //~ ERROR cycle detected when const-evaluating `a` [E0391]
const fn b() -> usize { a() }
const fn a() -> usize {
//~^ ERROR cycle detected when const-evaluating + checking `a` [E0391]
b()
}
const fn b() -> usize {
a()
}
const ARR: [i32; a()] = [5; 6];
fn main(){}
fn main() {}

View File

@ -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
|
LL | const fn a() -> usize { b() }
LL | const fn a() -> usize {
| ^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `b`...
--> $DIR/infinite-recursion-const-fn.rs:4:1
note: ...which requires const-evaluating + checking `b`...
--> $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: cycle used when const-evaluating `ARR::{{constant}}#0`
--> $DIR/infinite-recursion-const-fn.rs:5:18
= note: ...which again requires const-evaluating + checking `a`, completing the cycle
note: cycle used when const-evaluating + checking `ARR::{{constant}}#0`
--> $DIR/infinite-recursion-const-fn.rs:10:18
|
LL | const ARR: [i32; a()] = [5; 6];
| ^^^

View File

@ -1,6 +1,11 @@
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
|
LL | const FOO: usize = FOO;
@ -8,15 +13,10 @@ LL | const FOO: usize = FOO;
note: ...which requires const-evaluating + checking `FOO`...
--> $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;
| ^^^^^^^^^^^^^^^^^^^^^^^
= 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
|
LL | let _x: [u8; FOO]; // caused stack overflow prior to fix

View File

@ -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
|
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`...
--> $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,
| ^^^^^^^^^^^^^
= 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
--> $DIR/issue-23302-1.rs:3:1
|

View File

@ -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
|
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`...
--> $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,
| ^^^^^^^^^^^^^
= 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
--> $DIR/issue-23302-2.rs:3:1
|

View File

@ -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
|
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`...
--> $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;
| ^^^^^^^^^^^^^^^^^
= 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
|
LL | const B: i32 = A;
@ -23,15 +28,10 @@ LL | const B: i32 = A;
note: ...which requires const-evaluating + checking `B`...
--> $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;
| ^^^^^^^^^^^^^^^^^
= 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
error: aborting due to previous error

View File

@ -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
|
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`...
--> $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,
| ^
= 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
|
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`...
--> $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;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
--> $DIR/issue-36163.rs:1:1
|

View File

@ -1,4 +1,4 @@
pub static FOO: u32 = FOO;
//~^ ERROR cycle detected when const-evaluating `FOO`
//~^ ERROR cycle detected when const-evaluating + checking `FOO`
fn main() {}

View File

@ -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
|
LL | pub static FOO: u32 = FOO;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `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`
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 + checking `FOO`, completing the cycle
= note: cycle used when running analysis passes on this crate
error: aborting due to previous error

View File

@ -1,8 +1,8 @@
#[repr(u8)]
enum Alpha {
V1 = 41,
V2 = Self::V1 as u8 + 1, // OK; See #50072.
V3 = Self::V1 {} as u8 + 2, //~ ERROR cycle detected when const-evaluating
V2 = Self::V1 as u8 + 1, // OK; See #50072.
V3 = Self::V1 {} as u8 + 2, //~ ERROR cycle detected when simplifying constant
}
fn main() {}

View File

@ -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
|
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`...
--> $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,
| ^^^^^^^^
= 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
--> $DIR/self-in-enum-definition.rs:1:1
|
LL | / #[repr(u8)]
LL | | enum Alpha {
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 | | fn main() {}

View File

@ -4,23 +4,19 @@ error[E0080]: could not evaluate static initializer
LL | pub static mut B: () = unsafe { A = 1; };
| ^^^^^ 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
|
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `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`
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 + checking `C`, completing the cycle
= note: cycle used when running analysis passes on this crate
error: aborting due to 2 previous errors