move required_consts check to general post-mono-check function

This commit is contained in:
Ralf Jung 2023-09-11 09:52:45 +02:00
parent ccf817b9bb
commit 89ac57db4d
40 changed files with 319 additions and 257 deletions

View File

@ -2,6 +2,7 @@
use rustc_ast::InlineAsmOptions;
use rustc_index::IndexVec;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
@ -250,12 +251,21 @@ pub(crate) fn verify_func(
}
fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
if !crate::constant::check_constants(fx) {
fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
// compilation should have been aborted
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
return;
match fx.mir.post_mono_checks(fx.tcx, ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c))) {
Ok(()) => {}
Err(ErrorHandled::TooGeneric(span)) => {
span_bug!(span, "codegen encountered polymorphic constant");
}
Err(ErrorHandled::Reported(info, span)) => {
if !info.is_tainted_by_errors() {
fx.tcx.sess.span_err(span, "erroneous constant encountered");
}
fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
// compilation should have been aborted
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
return;
}
}
let arg_uninhabited = fx

View File

@ -2,9 +2,7 @@
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{
read_target_uint, AllocId, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
};
use rustc_middle::mir::interpret::{read_target_uint, AllocId, ConstValue, GlobalAlloc, Scalar};
use cranelift_module::*;
@ -33,16 +31,6 @@ impl ConstantCx {
}
}
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
let mut all_constants_ok = true;
for constant in &fx.mir.required_consts {
if eval_mir_constant(fx, constant).is_none() {
all_constants_ok = false;
}
}
all_constants_ok
}
pub(crate) fn codegen_static(tcx: TyCtxt<'_>, module: &mut dyn Module, def_id: DefId) {
let mut constants_cx = ConstantCx::new();
constants_cx.todo.push(TodoItem::Static(def_id));
@ -76,30 +64,20 @@ pub(crate) fn codegen_tls_ref<'tcx>(
pub(crate) fn eval_mir_constant<'tcx>(
fx: &FunctionCx<'_, '_, 'tcx>,
constant: &Constant<'tcx>,
) -> Option<(ConstValue<'tcx>, Ty<'tcx>)> {
) -> (ConstValue<'tcx>, Ty<'tcx>) {
let cv = fx.monomorphize(constant.literal);
// This cannot fail because we checked all required_consts in advance.
let val = cv
.eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(constant.span))
.map_err(|err| match err {
ErrorHandled::Reported(_) => {
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
}
ErrorHandled::TooGeneric => {
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
}
})
.ok();
val.map(|val| (val, cv.ty()))
.expect("erroneous constant not captured by required_consts");
(val, cv.ty())
}
pub(crate) fn codegen_constant_operand<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
constant: &Constant<'tcx>,
) -> CValue<'tcx> {
let (const_val, ty) = eval_mir_constant(fx, constant).unwrap_or_else(|| {
span_bug!(constant.span, "erroneous constant not captured by required_consts")
});
let (const_val, ty) = eval_mir_constant(fx, constant);
codegen_const_value(fx, const_val, ty)
}
@ -459,7 +437,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
operand: &Operand<'tcx>,
) -> Option<ConstValue<'tcx>> {
match operand {
Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).unwrap().0),
Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).0),
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
// inside a temporary before being passed to the intrinsic requiring the const argument.
// This code tries to find a single constant defining definition of the referenced local.

View File

@ -242,8 +242,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
}
}
InlineAsmOperand::Const { ref value } => {
let (const_value, ty) = crate::constant::eval_mir_constant(fx, value)
.unwrap_or_else(|| span_bug!(span, "asm const cannot be resolved"));
let (const_value, ty) = crate::constant::eval_mir_constant(fx, value);
let value = rustc_codegen_ssa::common::asm_const_to_str(
fx.tcx,
span,

View File

@ -1088,9 +1088,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
InlineAsmOperandRef::InOut { reg, late, in_value, out_place }
}
mir::InlineAsmOperand::Const { ref value } => {
let const_value = self
.eval_mir_constant(value)
.unwrap_or_else(|_| span_bug!(span, "asm const cannot be resolved"));
let const_value = self.eval_mir_constant(value);
let string = common::asm_const_to_str(
bx.tcx(),
span,

View File

@ -14,34 +14,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
&self,
bx: &mut Bx,
constant: &mir::Constant<'tcx>,
) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> {
let val = self.eval_mir_constant(constant)?;
) -> OperandRef<'tcx, Bx::Value> {
let val = self.eval_mir_constant(constant);
let ty = self.monomorphize(constant.ty());
Ok(OperandRef::from_const(bx, val, ty))
OperandRef::from_const(bx, val, ty)
}
pub fn eval_mir_constant(
&self,
constant: &mir::Constant<'tcx>,
) -> Result<ConstValue<'tcx>, ErrorHandled> {
pub fn eval_mir_constant(&self, constant: &mir::Constant<'tcx>) -> ConstValue<'tcx> {
self.monomorphize(constant.literal)
.eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span))
.map_err(|err| {
match err {
ErrorHandled::Reported(_) => {
self.cx
.tcx()
.sess
.emit_err(errors::ErroneousConstant { span: constant.span });
}
ErrorHandled::TooGeneric => {
self.cx.tcx().sess.diagnostic().emit_bug(
errors::PolymorphicConstantTooGeneric { span: constant.span },
);
}
}
err
})
.expect("erroneous constant not captured by required_consts")
}
/// This is a convenience helper for `simd_shuffle_indices`. It has the precondition

View File

@ -579,23 +579,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if let Some(dbg_var) = dbg_var {
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
if let Ok(operand) = self.eval_mir_constant_to_operand(bx, &c) {
self.set_debug_loc(bx, var.source_info);
let base = Self::spill_operand_to_stack(
operand,
Some(var.name.to_string()),
bx,
);
let operand = self.eval_mir_constant_to_operand(bx, &c);
self.set_debug_loc(bx, var.source_info);
let base =
Self::spill_operand_to_stack(operand, Some(var.name.to_string()), bx);
bx.dbg_var_addr(
dbg_var,
dbg_loc,
base.llval,
Size::ZERO,
&[],
fragment,
);
}
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, Size::ZERO, &[], fragment);
}
}
}

View File

@ -1,4 +1,5 @@
use crate::base;
use crate::errors;
use crate::traits::*;
use rustc_index::bit_set::BitSet;
use rustc_index::IndexVec;
@ -212,24 +213,21 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
// Evaluate all required consts; codegen later assumes that CTFE will never fail.
let mut all_consts_ok = true;
for const_ in &mir.required_consts {
if let Err(err) = fx.eval_mir_constant(const_) {
all_consts_ok = false;
match err {
// errored or at least linted
ErrorHandled::Reported(_) => {}
ErrorHandled::TooGeneric => {
span_bug!(const_.span, "codegen encountered polymorphic constant: {:?}", err)
}
}
// Rust post-monomorphization checks; we later rely on them.
match mir.post_mono_checks(cx.tcx(), ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c))) {
Ok(()) => {}
Err(ErrorHandled::TooGeneric(span)) => {
cx.tcx().sess.diagnostic().emit_bug(errors::PolymorphicConstantTooGeneric { span });
}
Err(ErrorHandled::Reported(info, span)) => {
if !info.is_tainted_by_errors() {
cx.tcx().sess.emit_err(errors::ErroneousConstant { span });
}
// This IR shouldn't ever be emitted, but let's try to guard against any of this code
// ever running.
start_bx.abort();
return;
}
}
if !all_consts_ok {
// We leave the IR in some half-built state here, and rely on this code not even being
// submitted to LLVM once an error was raised.
return;
}
let memory_locals = analyze::non_ssa_locals(&fx);

View File

@ -575,12 +575,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.codegen_consume(bx, place.as_ref())
}
mir::Operand::Constant(ref constant) => {
// This cannot fail because we checked all required_consts in advance.
self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|_err| {
span_bug!(constant.span, "erroneous constant not captured by required_consts")
})
}
mir::Operand::Constant(ref constant) => self.eval_mir_constant_to_operand(bx, constant),
}
}
}

View File

@ -4,7 +4,7 @@ use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, IntoDiagnostic, IntoDi
use rustc_middle::mir::AssertKind;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{layout::LayoutError, ConstInt};
use rustc_span::{ErrorGuaranteed, Span, Symbol};
use rustc_span::{ErrorGuaranteed, Span, Symbol, DUMMY_SP};
use super::InterpCx;
use crate::errors::{self, FrameNote, ReportErrorExt};
@ -134,11 +134,11 @@ where
// Don't emit a new diagnostic for these errors, they are already reported elsewhere or
// should remain silent.
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
ErrorHandled::TooGeneric
ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))
}
err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar),
err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span.unwrap_or(DUMMY_SP)),
err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
ErrorHandled::Reported(guar.into())
ErrorHandled::Reported(guar.into(), span.unwrap_or(DUMMY_SP))
}
// Report remaining errors.
_ => {
@ -152,7 +152,7 @@ where
// Use *our* span to label the interp error
err.span_label(our_span, msg);
ErrorHandled::Reported(err.emit().into())
ErrorHandled::Reported(err.emit().into(), span)
}
}
}

View File

@ -212,7 +212,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
key.param_env = key.param_env.with_user_facing();
match tcx.eval_to_const_value_raw(key) {
// try again with reveal all as requested
Err(ErrorHandled::TooGeneric) => {}
Err(ErrorHandled::TooGeneric(_)) => {}
// deduplicate calls
other => return other,
}
@ -259,7 +259,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
key.param_env = key.param_env.with_user_facing();
match tcx.eval_to_allocation_raw(key) {
// try again with reveal all as requested
Err(ErrorHandled::TooGeneric) => {}
Err(ErrorHandled::TooGeneric(_)) => {}
// deduplicate calls
other => return other,
}

View File

@ -7,7 +7,7 @@ use hir::CRATE_HIR_ID;
use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
use rustc_index::IndexVec;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{ErrorHandled, InterpError, InvalidMetaKind, ReportedErrorInfo};
use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{
self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
@ -21,7 +21,7 @@ use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayou
use super::{
AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace,
MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, PointerArithmetic,
MemPlaceMeta, Memory, MemoryKind, OpTy, Operand, Place, PlaceTy, Pointer, PointerArithmetic,
Projectable, Provenance, Scalar, StackPopJump,
};
use crate::errors::{self, ErroneousConstUsed};
@ -556,7 +556,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
>(
&self,
value: T,
) -> Result<T, InterpError<'tcx>> {
) -> Result<T, ErrorHandled> {
self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value)
}
@ -566,7 +566,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&self,
frame: &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>,
value: T,
) -> Result<T, InterpError<'tcx>> {
) -> Result<T, ErrorHandled> {
frame
.instance
.try_subst_mir_and_normalize_erasing_regions(
@ -574,7 +574,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.param_env,
ty::EarlyBinder::bind(value),
)
.map_err(|_| err_inval!(TooGeneric))
.map_err(|_| ErrorHandled::TooGeneric(self.cur_span()))
}
/// The `args` are assumed to already be in our interpreter "universe" (param_env).
@ -750,11 +750,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
if M::POST_MONO_CHECKS {
for ct in &body.required_consts {
let span = ct.span;
let ct = self.subst_from_current_frame_and_normalize_erasing_regions(ct.literal)?;
self.eval_mir_constant(&ct, Some(span), None)?;
}
// `ctfe_query` does some error message decoration that we want to be in effect here.
self.ctfe_query(None, |tcx| {
body.post_mono_checks(*tcx, self.param_env, |c| {
self.subst_from_current_frame_and_normalize_erasing_regions(c)
})
})?;
}
// done
@ -1059,28 +1060,29 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&self,
span: Option<Span>,
query: impl FnOnce(TyCtxtAt<'tcx>) -> Result<T, ErrorHandled>,
) -> InterpResult<'tcx, T> {
) -> Result<T, ErrorHandled> {
// Use a precise span for better cycle errors.
query(self.tcx.at(span.unwrap_or_else(|| self.cur_span()))).map_err(|err| {
match err {
ErrorHandled::Reported(err) => {
if !err.is_tainted_by_errors() && let Some(span) = span {
ErrorHandled::Reported(err, reported_span) => {
// We trust the provided span more than the one that came out of the query.
let span = span.unwrap_or(reported_span);
if !err.is_tainted_by_errors() {
// To make it easier to figure out where this error comes from, also add a note at the current location.
self.tcx.sess.emit_note(ErroneousConstUsed { span });
}
err_inval!(AlreadyReported(err))
}
ErrorHandled::TooGeneric => err_inval!(TooGeneric),
ErrorHandled::TooGeneric(_) => {}
}
.into()
err
})
}
pub fn eval_global(
&self,
gid: GlobalId<'tcx>,
span: Option<Span>,
instance: ty::Instance<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
let gid = GlobalId { instance, promoted: None };
// 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
@ -1091,10 +1093,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} else {
self.param_env
};
let val = self.ctfe_query(span, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?;
let val = self.ctfe_query(None, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?;
self.raw_const_to_mplace(val)
}
pub fn eval_mir_constant(
&self,
val: &mir::ConstantKind<'tcx>,
span: Option<Span>,
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
let const_val = self.ctfe_query(span, |tcx| val.eval(*tcx, self.param_env, span))?;
self.const_val_to_op(const_val, val.ty(), layout)
}
#[must_use]
pub fn dump_place(
&self,

View File

@ -8,15 +8,14 @@ use either::{Either, Left, Right};
use rustc_hir::def::Namespace;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
use rustc_middle::ty::{ConstInt, Ty, ValTree};
use rustc_middle::ty::{ConstInt, Ty};
use rustc_middle::{mir, ty};
use rustc_span::Span;
use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size};
use super::{
alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, GlobalId,
InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, PlaceTy, Pointer,
Projectable, Provenance, Scalar,
alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, InterpCx,
InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, PlaceTy, Pointer, Projectable,
Provenance, Scalar,
};
/// An `Immediate` represents a single immediate self-contained Rust value.
@ -693,54 +692,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(op)
}
fn eval_ty_constant(
&self,
val: ty::Const<'tcx>,
span: Option<Span>,
) -> InterpResult<'tcx, ValTree<'tcx>> {
Ok(match val.kind() {
ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(..) => {
throw_inval!(TooGeneric)
}
// FIXME(generic_const_exprs): `ConstKind::Expr` should be able to be evaluated
ty::ConstKind::Expr(_) => throw_inval!(TooGeneric),
ty::ConstKind::Error(reported) => {
throw_inval!(AlreadyReported(reported.into()))
}
ty::ConstKind::Unevaluated(uv) => {
let instance = self.resolve(uv.def, uv.args)?;
let cid = GlobalId { instance, promoted: None };
self.ctfe_query(span, |tcx| tcx.eval_to_valtree(self.param_env.and(cid)))?
.unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}"))
}
ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => {
span_bug!(self.cur_span(), "unexpected ConstKind in ctfe: {val:?}")
}
ty::ConstKind::Value(valtree) => valtree,
})
}
pub fn eval_mir_constant(
&self,
val: &mir::ConstantKind<'tcx>,
span: Option<Span>,
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
match *val {
mir::ConstantKind::Ty(ct) => {
let ty = ct.ty();
let valtree = self.eval_ty_constant(ct, span)?;
let const_val = self.tcx.valtree_to_const_val((ty, valtree));
self.const_val_to_op(const_val, ty, layout)
}
mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout),
mir::ConstantKind::Unevaluated(uv, _) => {
let instance = self.resolve(uv.def, uv.args)?;
Ok(self.eval_global(GlobalId { instance, promoted: uv.promoted }, span)?.into())
}
}
}
pub(crate) fn const_val_to_op(
&self,
val_val: ConstValue<'tcx>,

View File

@ -1596,9 +1596,12 @@ impl<'tcx> InferCtxt<'tcx> {
if let Some(ct) = tcx.thir_abstract_const(unevaluated.def)? {
let ct = tcx.expand_abstract_consts(ct.instantiate(tcx, args));
if let Err(e) = ct.error_reported() {
return Err(ErrorHandled::Reported(e.into()));
return Err(ErrorHandled::Reported(
e.into(),
span.unwrap_or(rustc_span::DUMMY_SP),
));
} else if ct.has_non_region_infer() || ct.has_non_region_param() {
return Err(ErrorHandled::TooGeneric);
return Err(ErrorHandled::TooGeneric(span.unwrap_or(rustc_span::DUMMY_SP)));
} else {
args = replace_param_and_infer_args_with_placeholder(tcx, args);
}

View File

@ -11,7 +11,7 @@ use rustc_errors::{
};
use rustc_macros::HashStable;
use rustc_session::CtfeBacktrace;
use rustc_span::def_id::DefId;
use rustc_span::{def_id::DefId, Span, DUMMY_SP};
use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange};
use std::borrow::Cow;
@ -21,16 +21,25 @@ use std::{any::Any, backtrace::Backtrace, fmt};
pub enum ErrorHandled {
/// Already reported an error for this evaluation, and the compilation is
/// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
Reported(ReportedErrorInfo),
Reported(ReportedErrorInfo, Span),
/// Don't emit an error, the evaluation failed because the MIR was generic
/// and the args didn't fully monomorphize it.
TooGeneric,
TooGeneric(Span),
}
impl From<ErrorGuaranteed> for ErrorHandled {
#[inline]
fn from(error: ErrorGuaranteed) -> ErrorHandled {
ErrorHandled::Reported(error.into())
ErrorHandled::Reported(error.into(), DUMMY_SP)
}
}
impl ErrorHandled {
pub fn with_span(self, span: Span) -> Self {
match self {
ErrorHandled::Reported(err, _span) => ErrorHandled::Reported(err, span),
ErrorHandled::TooGeneric(_span) => ErrorHandled::TooGeneric(span),
}
}
}
@ -162,6 +171,16 @@ impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
}
}
impl From<ErrorHandled> for InterpErrorInfo<'_> {
fn from(err: ErrorHandled) -> Self {
InterpError::InvalidProgram(match err {
ErrorHandled::Reported(r, _span) => InvalidProgramInfo::AlreadyReported(r),
ErrorHandled::TooGeneric(_span) => InvalidProgramInfo::TooGeneric,
})
.into()
}
}
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpError<'tcx>) -> Self {
InterpErrorInfo(Box::new(InterpErrorInfoInner {

View File

@ -61,8 +61,8 @@ impl<'tcx> TyCtxt<'tcx> {
let cid = GlobalId { instance, promoted: ct.promoted };
self.const_eval_global_id(param_env, cid, span)
}
Ok(None) => Err(ErrorHandled::TooGeneric),
Err(err) => Err(ErrorHandled::Reported(err.into())),
Ok(None) => Err(ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))),
Err(err) => Err(ErrorHandled::Reported(err.into(), span.unwrap_or(DUMMY_SP))),
}
}
@ -117,8 +117,8 @@ impl<'tcx> TyCtxt<'tcx> {
}
})
}
Ok(None) => Err(ErrorHandled::TooGeneric),
Err(err) => Err(ErrorHandled::Reported(err.into())),
Ok(None) => Err(ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))),
Err(err) => Err(ErrorHandled::Reported(err.into(), span.unwrap_or(DUMMY_SP))),
}
}

View File

@ -565,6 +565,37 @@ impl<'tcx> Body<'tcx> {
pub fn is_custom_mir(&self) -> bool {
self.injection_phase.is_some()
}
/// *Must* be called once the full substitution for this body is known, to ensure that the body
/// is indeed fit for code generation or consumption more generally.
///
/// Sadly there's no nice way to represent an "arbitrary normalizer", so we take one for
/// constants specifically. (`Option<GenericArgsRef>` could be used for that, but the fact
/// that `Instance::args_for_mir_body` is private and instead instance exposes normalization
/// functions makes it seem like exposing the generic args is not the intended strategy.)
///
/// Also sadly, CTFE doesn't even know whether it runs on MIR that is already polymorphic or still monomorphic,
/// so we cannot just immediately ICE on TooGeneric.
///
/// Returns Ok(()) if everything went fine, and `Err` if a problem occurred and got reported.
pub fn post_mono_checks(
&self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
normalize_const: impl Fn(ConstantKind<'tcx>) -> Result<ConstantKind<'tcx>, ErrorHandled>,
) -> Result<(), ErrorHandled> {
// For now, the only thing we have to check is is to ensure that all the constants used in
// the body successfully evaluate.
for &const_ in &self.required_consts {
let c = normalize_const(const_.literal)?;
c.eval(tcx, param_env, Some(const_.span)).map_err(|e| {
// The query results don't always have the span we want.
e.with_span(const_.span)
})?;
}
Ok(())
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
@ -2397,10 +2428,10 @@ impl<'tcx> ConstantKind<'tcx> {
pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
match self.eval(tcx, param_env, None) {
Ok(val) => Self::Val(val, self.ty()),
Err(ErrorHandled::Reported(guar)) => {
Err(ErrorHandled::Reported(guar, _span)) => {
Self::Ty(ty::Const::new_error(tcx, guar.into(), self.ty()))
}
Err(ErrorHandled::TooGeneric) => self,
Err(ErrorHandled::TooGeneric(_span)) => self,
}
}

View File

@ -478,8 +478,8 @@ impl<'tcx> AdtDef<'tcx> {
}
Err(err) => {
let msg = match err {
ErrorHandled::Reported(_) => "enum discriminant evaluation failed",
ErrorHandled::TooGeneric => "enum discriminant depends on generics",
ErrorHandled::Reported(..) => "enum discriminant evaluation failed",
ErrorHandled::TooGeneric(..) => "enum discriminant depends on generics",
};
tcx.sess.delay_span_bug(tcx.def_span(expr_did), msg);
None

View File

@ -300,7 +300,7 @@ impl<'tcx> Const<'tcx> {
| ConstKind::Infer(_)
| ConstKind::Bound(_, _)
| ConstKind::Placeholder(_)
| ConstKind::Expr(_) => Err(ErrorHandled::TooGeneric),
| ConstKind::Expr(_) => Err(ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))),
}
}
@ -309,8 +309,8 @@ impl<'tcx> Const<'tcx> {
pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
match self.eval(tcx, param_env, None) {
Ok(val) => Self::new_value(tcx, val, self.ty()),
Err(ErrorHandled::Reported(r)) => Self::new_error(tcx, r.into(), self.ty()),
Err(ErrorHandled::TooGeneric) => self,
Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into(), self.ty()),
Err(ErrorHandled::TooGeneric(_span)) => self,
}
}

View File

@ -566,7 +566,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
pattern
}
}
Err(ErrorHandled::TooGeneric) => {
Err(ErrorHandled::TooGeneric(_)) => {
// While `Reported | Linted` cases will have diagnostics emitted already
// it is not true for TooGeneric case, so we need to give user more information.
self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
@ -640,14 +640,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
.kind
} else {
// If that fails, convert it to an opaque constant pattern.
match tcx.const_eval_resolve(self.param_env, uneval, None) {
match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) {
Ok(val) => self.const_to_pat(mir::ConstantKind::Val(val, ty), id, span, None).kind,
Err(ErrorHandled::TooGeneric) => {
Err(ErrorHandled::TooGeneric(_)) => {
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
PatKind::Wild
}
Err(ErrorHandled::Reported(_)) => PatKind::Wild,
Err(ErrorHandled::Reported(..)) => PatKind::Wild,
}
}
}

View File

@ -752,8 +752,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
let param_env = ty::ParamEnv::reveal_all();
let val = match literal.eval(self.tcx, param_env, None) {
Ok(v) => v,
Err(ErrorHandled::Reported(_)) => return,
Err(ErrorHandled::TooGeneric) => span_bug!(
Err(ErrorHandled::Reported(..)) => return,
Err(ErrorHandled::TooGeneric(..)) => span_bug!(
self.body.source_info(location).span,
"collection encountered polymorphic constant: {:?}",
literal

View File

@ -949,8 +949,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
use rustc_middle::mir::interpret::ErrorHandled;
match self.infcx.try_const_eval_resolve(param_env, unevaluated, ty, None) {
Ok(ct) => Some(ct),
Err(ErrorHandled::Reported(e)) => Some(ty::Const::new_error(self.tcx(), e.into(), ty)),
Err(ErrorHandled::TooGeneric) => None,
Err(ErrorHandled::Reported(e, _)) => {
Some(ty::Const::new_error(self.tcx(), e.into(), ty))
}
Err(ErrorHandled::TooGeneric(_)) => None,
}
}

View File

@ -793,7 +793,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
span: tcx.def_span(unevaluated.def),
unevaluated: unevaluated,
});
Err(ErrorHandled::Reported(reported.into()))
Err(ErrorHandled::Reported(reported.into(), tcx.def_span(unevaluated.def)))
}
Err(err) => Err(err),
}

View File

@ -73,13 +73,13 @@ pub fn is_const_evaluatable<'tcx>(
ty::ConstKind::Unevaluated(uv) => {
let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
match concrete {
Err(ErrorHandled::TooGeneric) => {
Err(ErrorHandled::TooGeneric(_)) => {
Err(NotConstEvaluatable::Error(infcx.tcx.sess.delay_span_bug(
span,
"Missing value for constant, but no error reported?",
)))
}
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e.into())),
Err(ErrorHandled::Reported(e, _)) => Err(NotConstEvaluatable::Error(e.into())),
Ok(_) => Ok(()),
}
}
@ -132,7 +132,7 @@ pub fn is_const_evaluatable<'tcx>(
.emit()
}
Err(ErrorHandled::TooGeneric) => {
Err(ErrorHandled::TooGeneric(_)) => {
let err = if uv.has_non_region_infer() {
NotConstEvaluatable::MentionsInfer
} else if uv.has_non_region_param() {
@ -147,7 +147,7 @@ pub fn is_const_evaluatable<'tcx>(
Err(err)
}
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e.into())),
Err(ErrorHandled::Reported(e, _)) => Err(NotConstEvaluatable::Error(e.into())),
Ok(_) => Ok(()),
}
}

View File

@ -560,30 +560,31 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
let stalled_on = &mut pending_obligation.stalled_on;
let mut evaluate =
|c: Const<'tcx>| {
if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
match self.selcx.infcx.try_const_eval_resolve(
obligation.param_env,
unevaluated,
c.ty(),
Some(obligation.cause.span),
) {
Ok(val) => Ok(val),
Err(e) => match e {
ErrorHandled::TooGeneric => {
let mut evaluate = |c: Const<'tcx>| {
if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
match self.selcx.infcx.try_const_eval_resolve(
obligation.param_env,
unevaluated,
c.ty(),
Some(obligation.cause.span),
) {
Ok(val) => Ok(val),
Err(e) => {
match e {
ErrorHandled::TooGeneric(..) => {
stalled_on.extend(unevaluated.args.iter().filter_map(
TyOrConstInferVar::maybe_from_generic_arg,
));
Err(ErrorHandled::TooGeneric)
}
_ => Err(e),
},
_ => {}
}
Err(e)
}
} else {
Ok(c)
}
};
} else {
Ok(c)
}
};
match (evaluate(c1), evaluate(c2)) {
(Ok(c1), Ok(c2)) => {
@ -603,13 +604,14 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
),
}
}
(Err(ErrorHandled::Reported(reported)), _)
| (_, Err(ErrorHandled::Reported(reported))) => ProcessResult::Error(
(Err(ErrorHandled::Reported(reported, _)), _)
| (_, Err(ErrorHandled::Reported(reported, _))) => ProcessResult::Error(
CodeSelectionError(SelectionError::NotConstEvaluatable(
NotConstEvaluatable::Error(reported.into()),
)),
),
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
(Err(ErrorHandled::TooGeneric(_)), _)
| (_, Err(ErrorHandled::TooGeneric(_))) => {
if c1.has_non_region_infer() || c2.has_non_region_infer() {
ProcessResult::Unchanged
} else {

View File

@ -989,9 +989,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Err(_) => Ok(EvaluatedToErr),
}
}
(Err(ErrorHandled::Reported(_)), _)
| (_, Err(ErrorHandled::Reported(_))) => Ok(EvaluatedToErr),
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
(Err(ErrorHandled::Reported(..)), _)
| (_, Err(ErrorHandled::Reported(..))) => Ok(EvaluatedToErr),
(Err(ErrorHandled::TooGeneric(..)), _)
| (_, Err(ErrorHandled::TooGeneric(..))) => {
if c1.has_non_region_infer() || c2.has_non_region_infer() {
Ok(EvaluatedToAmbig)
} else {

View File

@ -204,7 +204,7 @@ fn is_value_unfrozen_raw<'tcx>(
// similar to 2., but with the a frozen variant) (e.g. borrowing
// `borrow_interior_mutable_const::enums::AssocConsts::TO_BE_FROZEN_VARIANT`).
// I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
err == ErrorHandled::TooGeneric
matches!(err, ErrorHandled::TooGeneric(..))
},
|val| val.map_or(true, |val| inner(cx, val, ty)),
)
@ -244,8 +244,8 @@ pub fn const_eval_resolve<'tcx>(
};
tcx.const_eval_global_id_for_typeck(param_env, cid, span)
},
Ok(None) => Err(ErrorHandled::TooGeneric),
Err(err) => Err(ErrorHandled::Reported(err.into())),
Ok(None) => Err(ErrorHandled::TooGeneric(span.unwrap_or(rustc_span::DUMMY_SP))),
Err(err) => Err(ErrorHandled::Reported(err.into(), span.unwrap_or(rustc_span::DUMMY_SP))),
}
}

View File

@ -142,9 +142,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn eval_path_scalar(&self, path: &[&str]) -> Scalar<Provenance> {
let this = self.eval_context_ref();
let instance = this.resolve_path(path, Namespace::ValueNS);
let cid = GlobalId { instance, promoted: None };
// We don't give a span -- this isn't actually used directly by the program anyway.
let const_val = this.eval_global(cid, None).unwrap_or_else(|err| {
let const_val = this.eval_global(instance).unwrap_or_else(|err| {
panic!("failed to evaluate required Rust item: {path:?}\n{err:?}")
});
this.read_scalar(&const_val)

View File

@ -3,7 +3,7 @@
// Cyclic assoc. const defaults don't error unless *used*
trait Tr {
const A: u8 = Self::B;
//~^ cycle detected when const-evaluating + checking `Tr::A`
//~^ cycle detected
const B: u8 = Self::A;
}

View File

@ -1,15 +1,25 @@
error[E0391]: cycle detected when const-evaluating + checking `Tr::A`
error[E0391]: cycle detected when simplifying constant for the type system `Tr::A`
--> $DIR/defaults-cyclic-fail.rs:5:5
|
LL | const A: u8 = Self::B;
| ^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `Tr::A`...
--> $DIR/defaults-cyclic-fail.rs:5:19
|
LL | const A: u8 = Self::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 const-evaluating + checking `Tr::B`...
--> $DIR/defaults-cyclic-fail.rs:8:19
|
LL | const B: u8 = Self::A;
| ^^^^^^^
= note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle
= note: ...which again requires simplifying constant for the type system `Tr::A`, completing the cycle
note: cycle used when const-evaluating + checking `main::promoted[1]`
--> $DIR/defaults-cyclic-fail.rs:16:16
|

View File

@ -4,7 +4,12 @@ error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-249
LL | const BAR: u32 = IMPL_REF_BAR;
| ^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `IMPL_REF_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 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;
@ -14,6 +19,11 @@ note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
|
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
| ^^^^^^^^^^^^^^^^^^
note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 11:19>::BAR`...
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
LL | const BAR: u32 = IMPL_REF_BAR;
| ^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 11:19>::BAR`...
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|

View File

@ -4,7 +4,12 @@ error[E0391]: cycle detected when elaborating drops for `FooDefault::BAR`
LL | const BAR: u32 = DEFAULT_REF_BAR;
| ^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `DEFAULT_REF_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 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;
@ -14,6 +19,11 @@ note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
|
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::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 const-evaluating + checking `FooDefault::BAR`...
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|

View File

@ -4,7 +4,12 @@ error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-249
LL | const BAR: u32 = TRAIT_REF_BAR;
| ^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `TRAIT_REF_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 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;
@ -14,6 +19,11 @@ note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
|
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 11:28>::BAR`...
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
LL | const BAR: u32 = TRAIT_REF_BAR;
| ^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 11:28>::BAR`...
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|

View File

@ -1,3 +1,9 @@
note: erroneous constant used
--> $DIR/issue-98629.rs:13:10
|
LL | [(); <i32 as Trait>::N]:,
| ^^^^^^^^^^^^^^^^^
error[E0046]: not all trait items implemented, missing: `N`
--> $DIR/issue-98629.rs:8:1
|

View File

@ -1,15 +1,25 @@
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 const-evaluating + checking `Foo::B::{constant#0}`...
--> $DIR/issue-36163.rs:4:9
|
LL | B = 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 const-evaluating + checking `A`...
--> $DIR/issue-36163.rs:1:18
|
LL | const A: isize = Foo::B as isize;
| ^^^^^^^^^^^^^^^
= 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 simplifying constant for the type system `Foo::B::{constant#0}`
--> $DIR/issue-36163.rs:4:9
|

View File

@ -10,6 +10,12 @@ note: type in trait
LL | const VALUE: usize;
| ^^^^^
note: erroneous constant used
--> $DIR/issue-70942-trait-vs-impl-mismatch.rs:13:18
|
LL | let _: [i32; Zero::VALUE] = [];
| ^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0326`.

View File

@ -1,10 +1,15 @@
error[E0391]: cycle detected when const-evaluating + checking `FOO`
error[E0391]: cycle detected when simplifying constant for the type system `FOO`
--> $DIR/issue-17252.rs:1:1
|
LL | const FOO: usize = FOO;
| ^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `FOO`...
--> $DIR/issue-17252.rs:1:20
|
LL | const FOO: usize = FOO;
| ^^^
|
= note: ...which immediately requires const-evaluating + checking `FOO` again
= note: ...which again requires simplifying constant for the type system `FOO`, completing the cycle
note: cycle used when const-evaluating + checking `main::{constant#0}`
--> $DIR/issue-17252.rs:4:18
|

View File

@ -1,10 +1,15 @@
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 immediately requires const-evaluating + checking `X::A::{constant#0}` again
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 again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle
note: cycle used when simplifying constant for the type system `X::A::{constant#0}`
--> $DIR/issue-23302-1.rs:4:9
|

View File

@ -1,10 +1,15 @@
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 immediately requires const-evaluating + checking `Y::A::{constant#0}` again
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 again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle
note: cycle used when simplifying constant for the type system `Y::A::{constant#0}`
--> $DIR/issue-23302-2.rs:4:9
|

View File

@ -1,15 +1,25 @@
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 const-evaluating + checking `A`...
--> $DIR/issue-23302-3.rs:1:16
|
LL | const A: i32 = 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 const-evaluating + checking `B`...
--> $DIR/issue-23302-3.rs:3:16
|
LL | const B: i32 = 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 simplifying constant for the type system `A`
--> $DIR/issue-23302-3.rs:1:1
|

View File

@ -13,6 +13,12 @@ LL | type MyA: TraitA;
LL | impl TraitB for B {
| ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation
note: erroneous constant used
--> $DIR/issue-69602-type-err-during-codegen-ice.rs:12:26
|
LL | const VALUE: usize = Self::MyA::VALUE;
| ^^^^^^^^^^^^^^^^
note: erroneous constant used
--> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17
|