diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 9159bc36987..54f82dcc8ae 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -723,11 +723,8 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool { } 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).eval_target_usize(fx.tcx, ParamEnv::reveal_all()); 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 a934b0767f1..b9d4bc9ff29 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -77,31 +77,9 @@ pub(crate) fn eval_mir_constant<'tcx>( fx: &FunctionCx<'_, '_, 'tcx>, constant: &Constant<'tcx>, ) -> Option<(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 Some((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 Some((val, constant_kind.ty())), - }; - - let val = fx - .tcx - .const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None) + let cv = fx.monomorphize(constant.literal); + 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"); @@ -111,7 +89,7 @@ pub(crate) fn eval_mir_constant<'tcx>( } }) .ok(); - val.map(|val| (val, constant_kind.ty())) + val.map(|val| (val, cv.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 067c824aba0..02f022b9454 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).unwrap(); + 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 babcf9bee24..4d7bd60ceca 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -24,43 +24,31 @@ pub fn eval_mir_constant( &self, constant: &mir::Constant<'tcx>, ) -> Result, ErrorHandled> { - 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 Ok(self.cx.tcx().valtree_to_const_val((ct.ty(), val))); + 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 => span_bug!( - constant.span, - "encountered bad ConstKind after monomorphizing: {:?}", - err - ), - }, - mir::ConstantKind::Unevaluated(uv, _) => uv, - mir::ConstantKind::Val(val, _) => return Ok(val), - }; - - self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).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 - }) + err + }) } /// 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>, @@ -80,7 +68,7 @@ pub fn eval_unevaluated_mir_constant_to_valtree( // `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_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 76ac2b2ac60..7e3be0b5d5f 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -71,6 +71,8 @@ fn into(self) -> ErrorGuaranteed { 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 3d45b4bdc33..570676ec4e3 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2342,29 +2342,39 @@ pub fn try_to_bool(self) -> Option { } #[inline] - pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { - 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())), - } + pub fn eval( + self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + span: Option, + ) -> Result, ErrorHandled> { + let uneval = match self { + ConstantKind::Ty(c) => { + if let ty::ConstKind::Unevaluated(uv) = c.kind() { + // Avoid the round-trip via valtree, evaluate directly to ConstValue. + uv.expand() } else { - self + // It's already a valtree, or an error. + let val = c.eval(tcx, param_env, span)?; + return Ok(tcx.valtree_to_const_val((self.ty(), val))); } } - Self::Val(_, _) => self, - Self::Unevaluated(uneval, ty) => { - // 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) => self, - Err(ErrorHandled::Reported(guar)) => { - Self::Ty(ty::Const::new_error(tcx, guar.into(), ty)) - } - } + ConstantKind::Unevaluated(uneval, _) => uneval, + ConstantKind::Val(val, _) => return Ok(val), + }; + // FIXME: We might want to have a `try_eval`-like function on `Unevaluated` + tcx.const_eval_resolve(param_env, uneval, span) + } + + /// Normalizes the constant to a value or an error 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(ErrorHandled::Reported(guar)) => { + Self::Ty(ty::Const::new_error(tcx, guar.into(), self.ty())) } + Err(ErrorHandled::TooGeneric) => self, } } @@ -2406,35 +2416,35 @@ pub fn try_eval_bits( } #[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( + self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> Option { + self.eval(tcx, param_env, None).ok()?.try_to_scalar() + } + + #[inline] + pub fn try_eval_scalar_int( + self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> Option { + self.try_eval_scalar(tcx, param_env)?.try_to_int().ok() + } + + #[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] @@ -2610,6 +2620,11 @@ impl<'tcx> UnevaluatedConst<'tcx> { pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> { UnevaluatedConst { def, args, promoted: Default::default() } } + + #[inline] + pub fn from_instance(instance: ty::Instance<'tcx>) -> Self { + UnevaluatedConst::new(instance.def_id(), instance.args) + } } /// A collection of projections into user types. diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index cce10417e1b..61e9000273f 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 @@ 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 @@ pub fn try_to_valtree(self) -> Option> { } } + #[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 @@ pub fn try_eval_bits( 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 @@ pub fn try_eval_target_usize( 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 @@ pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'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( + /// 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::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( - 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; + 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) 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)) + }; - // 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())), - } - } + // 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::Error(g) => Err(g.into()), + ConstKind::Param(_) + | ConstKind::Infer(_) + | ConstKind::Bound(_, _) + | ConstKind::Placeholder(_) + | ConstKind::Expr(_) => Err(ErrorHandled::TooGeneric), } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 7736183027f..c184154eacf 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 @@ fn lower_inline_const( 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 13550672ecc..11da9612f2f 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -209,7 +209,7 @@ fn handle_assign( && 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.into()), self.map()); } @@ -228,8 +228,7 @@ fn handle_rvalue( 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() + .try_eval_scalar(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()) @@ -304,8 +303,7 @@ fn handle_constant( ) -> Self::Value { constant .literal - .eval(self.tcx, self.param_env) - .try_to_scalar() + .try_eval_scalar(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 da19a3ba4fd..2550570af65 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -562,7 +562,7 @@ fn print_dyn_existential( 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()); + let ct = ct.normalize(self.tcx, ty::ParamEnv::reveal_all()); match ct.kind() { ty::ConstKind::Value(_) => {} 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 e4f5c4003c9..135410691f1 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 @@ fn report_similar_impl_candidates( 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 d2210c6d5d9..956f8e047d7 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -288,7 +288,7 @@ fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'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 b31c0e655fb..6444c01a67b 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -761,7 +761,7 @@ fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'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 87beaddc6c2..f785211c548 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 @@ fn try_fold_const( 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 af2ad547480..6c49e94dc31 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -129,19 +129,16 @@ pub fn from_const<'tcx>( 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 @@ pub fn from_const<'tcx>( ); 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/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f30384701cb..190b1b038b6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1863,7 +1863,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T // does nothing for `ConstKind::Param`. let ct = ty::Const::from_anon_const(cx.tcx, anon_const.def_id); let param_env = cx.tcx.param_env(anon_const.def_id); - print_const(cx, ct.eval(cx.tcx, param_env)) + print_const(cx, ct.normalize(cx.tcx, param_env)) } }; @@ -2082,7 +2082,7 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Str => Primitive(PrimitiveType::Str), ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None))), ty::Array(ty, mut n) => { - n = n.eval(cx.tcx, ty::ParamEnv::reveal_all()); + n = n.normalize(cx.tcx, ty::ParamEnv::reveal_all()); let n = print_const(cx, n); Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)), n.into()) }