From e76fd9f631e33796f0535c9d7b12730d7de535a7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 11 Sep 2023 12:36:45 +0200 Subject: [PATCH] cleanup eval() functions on our const types --- compiler/rustc_codegen_cranelift/src/base.rs | 6 +- .../rustc_codegen_cranelift/src/constant.rs | 28 +-- .../src/debuginfo/type_names.rs | 6 +- .../rustc_codegen_ssa/src/mir/constant.rs | 26 +-- .../rustc_const_eval/src/const_eval/mod.rs | 14 +- .../src/interpret/eval_context.rs | 35 ++-- .../rustc_const_eval/src/interpret/operand.rs | 57 +----- compiler/rustc_infer/src/infer/mod.rs | 16 +- .../rustc_middle/src/mir/interpret/error.rs | 8 +- compiler/rustc_middle/src/mir/mod.rs | 100 ++++------ compiler/rustc_middle/src/ty/consts.rs | 187 +++++++----------- .../rustc_mir_build/src/thir/pattern/mod.rs | 2 + .../src/dataflow_const_prop.rs | 8 +- compiler/rustc_symbol_mangling/src/v0.rs | 23 +-- .../src/traits/error_reporting/mod.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 2 +- .../src/traits/project.rs | 2 +- .../src/traits/query/normalize.rs | 2 +- compiler/rustc_transmute/src/lib.rs | 11 +- src/tools/miri/src/helpers.rs | 6 +- .../associated-consts/defaults-cyclic-fail.rs | 2 +- .../defaults-cyclic-fail.stderr | 16 +- ...9-assoc-const-static-recursion-impl.stderr | 7 +- ...onst-static-recursion-trait-default.stderr | 7 +- ...-assoc-const-static-recursion-trait.stderr | 7 +- tests/ui/const-ptr/out_of_bounds_read.stderr | 6 +- tests/ui/consts/invalid-union.64bit.stderr | 2 +- 27 files changed, 213 insertions(+), 375 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 0aa8dd9c7af53..3eadbc65aa6bf 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -733,11 +733,7 @@ fn codegen_stmt<'tcx>( } Rvalue::Repeat(ref operand, times) => { let operand = codegen_operand(fx, operand); - let times = fx - .monomorphize(times) - .eval(fx.tcx, ParamEnv::reveal_all()) - .try_to_bits(fx.tcx.data_layout.pointer_size) - .unwrap(); + let times = fx.monomorphize(times).try_to_target_usize(fx.tcx).unwrap(); if operand.layout().size.bytes() == 0 { // Do nothing for ZST's } else if fx.clif_type(operand.layout().ty) == Some(types::I8) { diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 3430971f51942..359ff2cf091dc 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -67,34 +67,12 @@ pub(crate) fn eval_mir_constant<'tcx>( fx: &FunctionCx<'_, '_, 'tcx>, constant: &Constant<'tcx>, ) -> (ConstValue<'tcx>, Ty<'tcx>) { - let constant_kind = fx.monomorphize(constant.literal); - let uv = match constant_kind { - ConstantKind::Ty(const_) => match const_.kind() { - ty::ConstKind::Unevaluated(uv) => uv.expand(), - ty::ConstKind::Value(val) => { - return (fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty()); - } - err => span_bug!( - constant.span, - "encountered bad ConstKind after monomorphizing: {:?}", - err - ), - }, - ConstantKind::Unevaluated(mir::UnevaluatedConst { def, .. }, _) - if fx.tcx.is_static(def) => - { - span_bug!(constant.span, "MIR constant refers to static"); - } - ConstantKind::Unevaluated(uv, _) => uv, - ConstantKind::Val(val, _) => return (val, constant_kind.ty()), - }; - // This cannot fail because we checked all required_consts in advance. let val = fx - .tcx - .const_eval_resolve(ty::ParamEnv::reveal_all(), uv, Some(constant.span)) + .monomorphize(constant.literal) + .eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(constant.span)) .expect("erroneous constant not captured by required_consts"); - (val, constant_kind.ty()) + (val, constant.ty()) } pub(crate) fn codegen_constant_operand<'tcx>( diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 067c824aba03a..a31feef7f684a 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -670,10 +670,8 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S // avoiding collisions and will make the emitted type names shorter. let hash_short = tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); - let ct = ct.eval(tcx, ty::ParamEnv::reveal_all()); - hcx.while_hashing_spans(false, |hcx| { - ct.to_valtree().hash_stable(hcx, &mut hasher) - }); + let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), None); + hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher)); hasher.finish::() }); diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index e706cedee7716..4b17502b527ac 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -21,33 +21,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } pub fn eval_mir_constant(&self, constant: &mir::Constant<'tcx>) -> ConstValue<'tcx> { - let ct = self.monomorphize(constant.literal); - let uv = match ct { - mir::ConstantKind::Ty(ct) => match ct.kind() { - ty::ConstKind::Unevaluated(uv) => uv.expand(), - ty::ConstKind::Value(val) => { - return self.cx.tcx().valtree_to_const_val((ct.ty(), val)); - } - err => span_bug!( - constant.span, - "encountered bad ConstKind after monomorphizing: {:?}", - err - ), - }, - mir::ConstantKind::Unevaluated(uv, _) => uv, - mir::ConstantKind::Val(val, _) => return val, - }; - // This cannot fail because we checked all required_consts in advance. - self.cx - .tcx() - .const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None) + self.monomorphize(constant.literal) + .eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span)) .expect("erroneous constant not captured by required_consts") } /// This is a convenience helper for `simd_shuffle_indices`. It has the precondition /// that the given `constant` is an `ConstantKind::Unevaluated` and must be convertible to /// a `ValTree`. If you want a more general version of this, talk to `wg-const-eval` on zulip. + /// + /// Note that this function is cursed, since usually MIR consts should not be evaluated to valtrees! pub fn eval_unevaluated_mir_constant_to_valtree( &self, constant: &mir::Constant<'tcx>, @@ -67,7 +51,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // `simd_shuffle` call without wrapping the constant argument in a `const {}` block, but // the user pass through arbitrary expressions. // FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a real - // const generic. + // const generic, and get rid of this entire function. other => span_bug!(constant.span, "{other:#?}"), }; let uv = self.monomorphize(uv); diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 5327fa5ce39bd..ccd0133cb8987 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -3,7 +3,7 @@ use crate::errors::MaxNumNodesInConstErr; use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, Scalar}; use rustc_middle::mir; -use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; +use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{source_map::DUMMY_SP, symbol::Symbol}; @@ -70,15 +70,19 @@ pub(crate) fn eval_to_valtree<'tcx>( Ok(valtree) => Ok(Some(valtree)), Err(err) => { let did = cid.instance.def_id(); + let span = tcx.hir().span_if_local(did); let global_const_id = cid.display(tcx); match err { ValTreeCreationError::NodesOverflow => { - let span = tcx.hir().span_if_local(did); - tcx.sess.emit_err(MaxNumNodesInConstErr { span, global_const_id }); - + let g = tcx.sess.emit_err(MaxNumNodesInConstErr { span, global_const_id }); + Err(ErrorHandled::Reported(g.into(), span.unwrap_or(DUMMY_SP))) + } + ValTreeCreationError::NonSupportedType | ValTreeCreationError::Other => { + // Sadly we cannot report an error or `delay_span_bug` here; pattern + // construction calls this function speculatively needs the `None` to fall back + // to MIR constant value. Ok(None) } - ValTreeCreationError::NonSupportedType | ValTreeCreationError::Other => Ok(None), } } } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 794640d3d8333..f2daebaa8ef73 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -20,9 +20,9 @@ use rustc_span::Span; use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout}; use super::{ - AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, - MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, PointerArithmetic, - Projectable, Provenance, Scalar, StackPopJump, + AllocId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, + Memory, MemoryKind, OpTy, Operand, Place, PlaceTy, Pointer, PointerArithmetic, Projectable, + Provenance, Scalar, StackPopJump, }; use crate::errors::{self, ErroneousConstUsed}; use crate::util; @@ -1078,23 +1078,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }) } - pub fn eval_global( + pub fn eval_ty_constant( &self, - gid: GlobalId<'tcx>, + val: ty::Const<'tcx>, span: Option, - ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { - // 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.ctfe_query(span, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?; - self.raw_const_to_mplace(val) + ) -> InterpResult<'tcx, ty::ValTree<'tcx>> { + Ok(self.ctfe_query(span, |tcx| val.eval(*tcx, self.param_env, span))?) + } + + pub fn eval_mir_constant( + &self, + val: &mir::ConstantKind<'tcx>, + span: Option, + layout: Option>, + ) -> 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] diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 26dd9098bb5d6..09ab93ef87d0e 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -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, - ) -> 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, - layout: Option>, - ) -> 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>, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index ef27a8f2c7a30..60e1704acb8a0 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -6,7 +6,6 @@ pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; pub use combine::ObligationEmittingRelation; -use rustc_data_structures::undo_log::UndoLogs; use self::opaque_types::OpaqueTypeStorage; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; @@ -17,6 +16,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::Rollback; +use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify as ut; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -36,7 +36,7 @@ use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtx use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid}; use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef}; use rustc_span::symbol::Symbol; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use std::cell::{Cell, RefCell}; use std::fmt; @@ -1552,15 +1552,15 @@ impl<'tcx> InferCtxt<'tcx> { // variables let tcx = self.tcx; if args.has_non_region_infer() { - if let Some(ct) = tcx.thir_abstract_const(unevaluated.def)? { + if let Some(ct) = tcx + .thir_abstract_const(unevaluated.def) + .map_err(|e| ErrorHandled::Reported(e.into(), DUMMY_SP))? + { let ct = tcx.expand_abstract_consts(ct.instantiate(tcx, args)); if let Err(e) = ct.error_reported() { - return Err(ErrorHandled::Reported( - e.into(), - span.unwrap_or(rustc_span::DUMMY_SP), - )); + return Err(ErrorHandled::Reported(e.into(), span.unwrap_or(DUMMY_SP))); } else if ct.has_non_region_infer() || ct.has_non_region_param() { - return Err(ErrorHandled::TooGeneric(span.unwrap_or(rustc_span::DUMMY_SP))); + return Err(ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))); } else { args = replace_param_and_infer_args_with_placeholder(tcx, args); } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 9cb82a078be29..e3758d1ef5bb7 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -11,7 +11,7 @@ use rustc_errors::{ }; use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; -use rustc_span::{def_id::DefId, Span, DUMMY_SP}; +use rustc_span::{def_id::DefId, Span}; use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange}; use std::borrow::Cow; @@ -27,12 +27,12 @@ pub enum ErrorHandled { TooGeneric(Span), } -impl From for ErrorHandled { +/*impl From for ErrorHandled { #[inline] fn from(error: ErrorGuaranteed) -> ErrorHandled { ErrorHandled::Reported(error.into(), DUMMY_SP) } -} +}*/ impl ErrorHandled { pub fn with_span(self, span: Span) -> Self { @@ -80,6 +80,8 @@ TrivialTypeTraversalAndLiftImpls! { ErrorHandled } pub type EvalToAllocationRawResult<'tcx> = Result, ErrorHandled>; pub type EvalToConstValueResult<'tcx> = Result, ErrorHandled>; +/// `Ok(None)` indicates the constant was fine, but the valtree couldn't be constructed. +/// This is needed in `thir::pattern::lower_inline_const`. pub type EvalToValTreeResult<'tcx> = Result>, ErrorHandled>; pub fn struct_error<'tcx>( diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 282f320706494..5c5e6ce60891c 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -549,28 +549,9 @@ impl<'tcx> Body<'tcx> { // 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 uv = match normalize_const(const_.literal)? { - ConstantKind::Ty(ct) => match ct.kind() { - ty::ConstKind::Unevaluated(uv) => uv.expand(), - ty::ConstKind::Value(..) => { - // These are already evaluated, so this cannot fail. - return Ok(()); - } - ty::ConstKind::Error(err) => { - return Err(ErrorHandled::Reported(err.into(), const_.span)); - } - ty::ConstKind::Param(..) - | ty::ConstKind::Infer(..) - | ty::ConstKind::Bound(..) - | ty::ConstKind::Placeholder(..) - | ty::ConstKind::Expr(..) => return Err(ErrorHandled::TooGeneric(const_.span)), - }, - ConstantKind::Unevaluated(uv, _) => uv, - ConstantKind::Val(..) => return Ok(()), - }; - tcx.const_eval_resolve(param_env, uv, Some(const_.span)).map_err(|e| - // The query results don't always have the span we want. - e.with_span(const_.span))?; + let c = normalize_const(const_.literal)?; + // The query results don't always have the span we want, so we use our own. + c.eval(tcx, param_env, Some(const_.span)).map_err(|e| e.with_span(const_.span))?; } Ok(()) @@ -2386,29 +2367,31 @@ impl<'tcx> ConstantKind<'tcx> { } #[inline] - pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { + pub fn eval( + self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + span: Option, + ) -> Result, ErrorHandled> { match self { - Self::Ty(c) => { - if let Some(val) = c.try_eval_for_mir(tcx, param_env) { - match val { - Ok(val) => Self::Val(val, c.ty()), - Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())), - } - } else { - self - } + ConstantKind::Ty(c) => { + let val = c.eval(tcx, param_env, span)?; + Ok(tcx.valtree_to_const_val((self.ty(), val))) } - Self::Val(_, _) => self, - Self::Unevaluated(uneval, ty) => { + ConstantKind::Unevaluated(uneval, _) => { // FIXME: We might want to have a `try_eval`-like function on `Unevaluated` - match tcx.const_eval_resolve(param_env, uneval, None) { - Ok(val) => Self::Val(val, ty), - Err(ErrorHandled::TooGeneric(_span)) => self, - Err(ErrorHandled::Reported(guar, _span)) => { - Self::Ty(ty::Const::new_error(tcx, guar.into(), ty)) - } - } + tcx.const_eval_resolve(param_env, uneval, span) } + ConstantKind::Val(val, _) => Ok(val), + } + } + + /// Normalizes the constant to a value if possible. + #[inline] + 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(_) => self, } } @@ -2450,35 +2433,26 @@ impl<'tcx> ConstantKind<'tcx> { } #[inline] - pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option { - match self { - Self::Ty(ct) => ct.try_eval_bool(tcx, param_env), - Self::Val(val, _) => val.try_to_bool(), - Self::Unevaluated(uneval, _) => { - match tcx.const_eval_resolve(param_env, *uneval, None) { - Ok(val) => val.try_to_bool(), - Err(_) => None, - } - } - } + pub fn try_eval_scalar_int( + self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> Option { + self.eval(tcx, param_env, None).ok()?.try_to_scalar_int() + } + + #[inline] + pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option { + self.try_eval_scalar_int(tcx, param_env)?.try_into().ok() } #[inline] pub fn try_eval_target_usize( - &self, + self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Option { - match self { - Self::Ty(ct) => ct.try_eval_target_usize(tcx, param_env), - Self::Val(val, _) => val.try_to_target_usize(tcx), - Self::Unevaluated(uneval, _) => { - match tcx.const_eval_resolve(param_env, *uneval, None) { - Ok(val) => val.try_to_target_usize(tcx), - Err(_) => None, - } - } - } + self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok() } #[inline] diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 4ac864cdef662..ffc109918a7ec 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,5 +1,5 @@ use crate::middle::resolve_bound_vars as rbv; -use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar}; +use crate::mir::interpret::{AllocId, ErrorHandled, LitToConstInput, Scalar}; use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; @@ -14,7 +14,7 @@ mod valtree; pub use int::*; pub use kind::*; -use rustc_span::ErrorGuaranteed; +use rustc_span::Span; use rustc_span::DUMMY_SP; use rustc_target::abi::Size; pub use valtree::*; @@ -36,16 +36,6 @@ pub struct ConstData<'tcx> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstData<'_>, 40); -enum EvalMode { - Typeck, - Mir, -} - -enum EvalResult<'tcx> { - ValTree(ty::ValTree<'tcx>), - ConstVal(ConstValue<'tcx>), -} - impl<'tcx> Const<'tcx> { #[inline] pub fn ty(self) -> Ty<'tcx> { @@ -302,6 +292,18 @@ impl<'tcx> Const<'tcx> { } } + #[inline] + /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of + /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it + /// contains const generic parameters or pointers). + pub fn try_eval_scalar_int( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> Option { + self.eval(tcx, param_env, None).ok()?.try_to_scalar_int() + } + #[inline] /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it @@ -312,15 +314,16 @@ impl<'tcx> Const<'tcx> { param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, ) -> Option { + let int = self.try_eval_scalar_int(tcx, param_env)?; assert_eq!(self.ty(), ty); let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; // if `ty` does not depend on generic parameters, use an empty param_env - self.eval(tcx, param_env).try_to_bits(size) + int.to_bits(size).ok() } #[inline] pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - self.eval(tcx, param_env).try_to_bool() + self.try_eval_scalar_int(tcx, param_env)?.try_into().ok() } #[inline] @@ -329,21 +332,16 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option { - self.eval(tcx, param_env).try_to_target_usize(tcx) + self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok() } + /// Normalizes the constant to a value or an error if possible. #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the - /// unevaluated constant. - pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> { - if let Some(val) = self.try_eval_for_typeck(tcx, param_env) { - match val { - Ok(val) => ty::Const::new_value(tcx, val, self.ty()), - Err(guar) => ty::Const::new_error(tcx, guar, self.ty()), - } - } else { - // Either the constant isn't evaluatable or ValTree creation failed. - self + 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, } } @@ -361,105 +359,54 @@ impl<'tcx> Const<'tcx> { .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary - /// return `None`. - // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. - pub fn try_eval_for_mir( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option, ErrorGuaranteed>> { - match self.try_eval_inner(tcx, param_env, EvalMode::Mir) { - Some(Ok(EvalResult::ValTree(_))) => unreachable!(), - Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)), - Some(Err(e)) => Some(Err(e)), - None => None, - } - } - - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary - /// return `None`. - // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. - pub fn try_eval_for_typeck( + /// Returns the evaluated constant + pub fn eval( self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, - ) -> Option, ErrorGuaranteed>> { - match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) { - Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)), - Some(Ok(EvalResult::ConstVal(_))) => unreachable!(), - Some(Err(e)) => Some(Err(e)), - None => None, - } - } - - #[inline] - fn try_eval_inner( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - eval_mode: EvalMode, - ) -> Option, ErrorGuaranteed>> { + span: Option, + ) -> Result, ErrorHandled> { assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}"); - if let ConstKind::Unevaluated(unevaluated) = self.kind() { - use crate::mir::interpret::ErrorHandled; - - // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` - // also does later, but we want to do it before checking for - // inference variables. - // Note that we erase regions *before* calling `with_reveal_all_normalized`, - // so that we don't try to invoke this query with - // any region variables. - - // HACK(eddyb) when the query key would contain inference variables, - // attempt using identity args and `ParamEnv` instead, that will succeed - // when the expression doesn't depend on any parameters. - // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that - // we can call `infcx.const_eval_resolve` which handles inference variables. - let param_env_and = if (param_env, unevaluated).has_non_region_infer() { - tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst { - def: unevaluated.def, - args: GenericArgs::identity_for_item(tcx, unevaluated.def), - }) - } else { - tcx.erase_regions(param_env) - .with_reveal_all_normalized(tcx) - .and(tcx.erase_regions(unevaluated)) - }; - - // FIXME(eddyb) maybe the `const_eval_*` methods should take - // `ty::ParamEnvAnd` instead of having them separate. - let (param_env, unevaluated) = param_env_and.into_parts(); - // try to resolve e.g. associated constants to their definition on an impl, and then - // evaluate the const. - match eval_mode { - EvalMode::Typeck => { - match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) { - // NOTE(eddyb) `val` contains no lifetimes/types/consts, - // and we use the original type, so nothing from `args` - // (which may be identity args, see above), - // can leak through `val` into the const we return. - Ok(val) => Some(Ok(EvalResult::ValTree(val?))), - Err(ErrorHandled::TooGeneric(_)) => None, - Err(ErrorHandled::Reported(e, _)) => Some(Err(e.into())), - } - } - EvalMode::Mir => { - match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) { - // NOTE(eddyb) `val` contains no lifetimes/types/consts, - // and we use the original type, so nothing from `args` - // (which may be identity args, see above), - // can leak through `val` into the const we return. - Ok(val) => Some(Ok(EvalResult::ConstVal(val))), - Err(ErrorHandled::TooGeneric(_)) => None, - Err(ErrorHandled::Reported(e, _)) => Some(Err(e.into())), - } - } + match self.kind() { + ConstKind::Unevaluated(unevaluated) => { + // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` + // also does later, but we want to do it before checking for + // inference variables. + // Note that we erase regions *before* calling `with_reveal_all_normalized`, + // so that we don't try to invoke this query with + // any region variables. + + // HACK(eddyb) when the query key would contain inference variables, + // attempt using identity args and `ParamEnv` instead, that will succeed + // when the expression doesn't depend on any parameters. + // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that + // we can call `infcx.const_eval_resolve` which handles inference variables. + let param_env_and = if (param_env, unevaluated).has_non_region_infer() { + tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst { + def: unevaluated.def, + args: GenericArgs::identity_for_item(tcx, unevaluated.def), + }) + } else { + tcx.erase_regions(param_env) + .with_reveal_all_normalized(tcx) + .and(tcx.erase_regions(unevaluated)) + }; + + // FIXME(eddyb) maybe the `const_eval_*` methods should take + // `ty::ParamEnvAnd` instead of having them separate. + let (param_env, unevaluated) = param_env_and.into_parts(); + // try to resolve e.g. associated constants to their definition on an impl, and then + // evaluate the const. + let c = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)?; + Ok(c.expect("`ty::Const::eval` called on a non-valtree-compatible type")) } - } else { - None + ConstKind::Value(val) => Ok(val), + ConstKind::Param(_) + | ConstKind::Infer(_) + | ConstKind::Bound(_, _) + | ConstKind::Placeholder(_) + | ConstKind::Error(_) + | ConstKind::Expr(_) => Err(ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))), } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index b29fa2ff68b97..110c571edc7b6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -626,6 +626,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args: args }; // First try using a valtree in order to destructure the constant into a pattern. + // FIXME: replace "try to do a thing, then fall back to another thing" + // but something more principled, like a trait query checking whether this can be turned into a valtree. if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span)) { diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 333a14be996b0..e3605ed8ccce2 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -196,7 +196,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { && let operand_ty = operand.ty(self.local_decls, self.tcx) && let Some(operand_ty) = operand_ty.builtin_deref(true) && let ty::Array(_, len) = operand_ty.ty.kind() - && let Some(len) = ConstantKind::Ty(*len).eval(self.tcx, self.param_env).try_to_scalar_int() + && let Some(len) = ConstantKind::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env) { state.insert_value_idx(target_len, FlatSet::Elem(len), self.map()); } @@ -215,8 +215,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { let place_ty = place.ty(self.local_decls, self.tcx); if let ty::Array(_, len) = place_ty.ty.kind() { ConstantKind::Ty(*len) - .eval(self.tcx, self.param_env) - .try_to_scalar_int() + .try_eval_scalar_int(self.tcx, self.param_env) .map_or(FlatSet::Top, FlatSet::Elem) } else if let [ProjectionElem::Deref] = place.projection[..] { state.get_len(place.local.into(), self.map()) @@ -290,8 +289,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { ) -> Self::Value { constant .literal - .eval(self.tcx, self.param_env) - .try_to_scalar_int() + .try_eval_scalar_int(self.tcx, self.param_env) .map_or(FlatSet::Top, FlatSet::Elem) } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index da19a3ba4fd61..51fbafd78c074 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -562,26 +562,17 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { fn print_const(mut self, ct: ty::Const<'tcx>) -> Result { // We only mangle a typed value if the const can be evaluated. - let ct = ct.eval(self.tcx, ty::ParamEnv::reveal_all()); - match ct.kind() { - ty::ConstKind::Value(_) => {} - + let Ok(c) = ct.eval(self.tcx, ty::ParamEnv::reveal_all(), None) else { // Placeholders (should be demangled as `_`). // NOTE(eddyb) despite `Unevaluated` having a `DefId` (and therefore // a path), even for it we still need to encode a placeholder, as // the path could refer back to e.g. an `impl` using the constant. - ty::ConstKind::Unevaluated(_) - | ty::ConstKind::Expr(_) - | ty::ConstKind::Param(_) - | ty::ConstKind::Infer(_) - | ty::ConstKind::Bound(..) - | ty::ConstKind::Placeholder(_) - | ty::ConstKind::Error(_) => { - // Never cached (single-character). - self.push("p"); - return Ok(self); - } - } + // Never cached (single-character). + self.push("p"); + return Ok(self); + }; + // FIXME: here we forget that we already have a value.. + let ct = ty::Const::new_value(self.tcx, c, ct.ty()); if let Some(&i) = self.consts.get(&ct) { return self.print_backref(i); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 746a38f956ab3..8d53f3d3ca218 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2054,7 +2054,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { tcx: self.tcx, ty_op: |ty| ty, lt_op: |lt| lt, - ct_op: |ct| ct.eval(self.tcx, ty::ParamEnv::empty()), + ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()), }); cand }) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index d2210c6d5d91b..956f8e047d705 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -288,7 +288,7 @@ pub fn normalize_param_env_or_error<'tcx>( // should actually be okay since without `feature(generic_const_exprs)` the only // const arguments that have a non-empty param env are array repeat counts. These // do not appear in the type system though. - c.eval(self.0, ty::ParamEnv::empty()) + c.normalize(self.0, ty::ParamEnv::empty()) } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index b31c0e655fbb3..6444c01a67b51 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -761,7 +761,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx self.selcx.infcx, &mut self.universes, constant, - |constant| constant.eval(tcx, self.param_env), + |constant| constant.normalize(tcx, self.param_env), ) } } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 87beaddc6c200..f785211c54861 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -358,7 +358,7 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> self.infcx, &mut self.universes, constant, - |constant| constant.eval(self.infcx.tcx, self.param_env), + |constant| constant.normalize(self.infcx.tcx, self.param_env), )) } diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index af2ad54748025..6c49e94dc310b 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -129,19 +129,16 @@ mod rustc { c: Const<'tcx>, ) -> Option { use rustc_middle::ty::ScalarInt; - use rustc_middle::ty::TypeVisitableExt; use rustc_span::symbol::sym; - let c = c.eval(tcx, param_env); - - if let Err(err) = c.error_reported() { + let Ok(cv) = c.eval(tcx, param_env, None) else { return Some(Self { alignment: true, lifetimes: true, safety: true, validity: true, }); - } + }; let adt_def = c.ty().ty_adt_def()?; @@ -153,8 +150,8 @@ mod rustc { ); let variant = adt_def.non_enum_variant(); - let fields = match c.try_to_valtree() { - Some(ValTree::Branch(branch)) => branch, + let fields = match cv { + ValTree::Branch(branch) => branch, _ => { return Some(Self { alignment: true, diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 0c7e82781476d..a5663ecc2656e 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -142,9 +142,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn eval_path_scalar(&self, path: &[&str]) -> Scalar { let this = self.eval_context_ref(); let instance = this.resolve_path(path, Namespace::ValueNS); - let cid = GlobalId { instance, promoted: None }; + // HACK: The actual type doesn't matter for what we do, so we use a fake type. + let ty = this.tcx.types.unit; + let const_ = mir::ConstantKind::Unevaluated(mir::UnevaluatedConst::new(instance.def_id(), ty::List::empty()), ty); // 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_mir_constant(&const_, None, None).unwrap_or_else(|err| { panic!("failed to evaluate required Rust item: {path:?}\n{err:?}") }); this.read_scalar(&const_val) diff --git a/tests/ui/associated-consts/defaults-cyclic-fail.rs b/tests/ui/associated-consts/defaults-cyclic-fail.rs index a1c6840a0f1b3..9ef0003da173f 100644 --- a/tests/ui/associated-consts/defaults-cyclic-fail.rs +++ b/tests/ui/associated-consts/defaults-cyclic-fail.rs @@ -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; } diff --git a/tests/ui/associated-consts/defaults-cyclic-fail.stderr b/tests/ui/associated-consts/defaults-cyclic-fail.stderr index 14622a3bd23a7..e29c32f5dfdaf 100644 --- a/tests/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/tests/ui/associated-consts/defaults-cyclic-fail.stderr @@ -1,9 +1,14 @@ -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 | @@ -14,12 +19,7 @@ note: ...which requires const-evaluating + checking `Tr::B`... | LL | const B: u8 = Self::A; | ^^^^^^^ -note: ...which requires simplifying constant for the type system `Tr::A`... - --> $DIR/defaults-cyclic-fail.rs:5:5 - | -LL | const A: u8 = Self::B; - | ^^^^^^^^^^^ - = 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 | diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr index f711e84fd0e1d..4418fb7556bd9 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -4,7 +4,12 @@ error[E0391]: cycle detected when elaborating drops for ` $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; diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr index add646fe85502..392cd5e3443ae 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -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 = ::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 = ::BAR; diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index c50202e5da89b..6cbddca9c62a0 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -4,7 +4,12 @@ error[E0391]: cycle detected when elaborating drops for ` $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 + | +LL | const TRAIT_REF_BAR: u32 = ::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 = ::BAR; diff --git a/tests/ui/const-ptr/out_of_bounds_read.stderr b/tests/ui/const-ptr/out_of_bounds_read.stderr index c5c0a1cdefcb4..3368a49d81976 100644 --- a/tests/ui/const-ptr/out_of_bounds_read.stderr +++ b/tests/ui/const-ptr/out_of_bounds_read.stderr @@ -1,7 +1,7 @@ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: dereferencing pointer failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + = note: dereferencing pointer failed: alloc6 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL @@ -14,7 +14,7 @@ LL | const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: dereferencing pointer failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + = note: dereferencing pointer failed: alloc6 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL @@ -29,7 +29,7 @@ LL | const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: dereferencing pointer failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + = note: dereferencing pointer failed: alloc6 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL diff --git a/tests/ui/consts/invalid-union.64bit.stderr b/tests/ui/consts/invalid-union.64bit.stderr index 07f36ee283264..3689cf71dd07a 100644 --- a/tests/ui/consts/invalid-union.64bit.stderr +++ b/tests/ui/consts/invalid-union.64bit.stderr @@ -6,7 +6,7 @@ LL | fn main() { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc7────────╼ │ ╾──────╼ + ╾───────alloc8────────╼ │ ╾──────╼ } note: erroneous constant used