diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 570676ec4e3..d56f2246c99 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2299,18 +2299,6 @@ impl<'tcx> ConstantKind<'tcx> { } } - #[inline] - pub fn try_to_value(self, tcx: TyCtxt<'tcx>) -> Option> { - match self { - ConstantKind::Ty(c) => match c.kind() { - ty::ConstKind::Value(valtree) => Some(tcx.valtree_to_const_val((c.ty(), valtree))), - _ => None, - }, - ConstantKind::Val(val, _) => Some(val), - ConstantKind::Unevaluated(..) => None, - } - } - #[inline] pub fn try_to_scalar(self) -> Option { match self { @@ -2378,43 +2366,6 @@ impl<'tcx> ConstantKind<'tcx> { } } - /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. - #[inline] - pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { - self.try_eval_bits(tcx, param_env, ty) - .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) - } - - #[inline] - pub fn try_eval_bits( - &self, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - ) -> Option { - match self { - Self::Ty(ct) => ct.try_eval_bits(tcx, param_env, ty), - Self::Val(val, t) => { - assert_eq!(*t, ty); - let size = - tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; - val.try_to_bits(size) - } - Self::Unevaluated(uneval, ty) => { - match tcx.const_eval_resolve(param_env, *uneval, None) { - Ok(val) => { - let size = tcx - .layout_of(param_env.with_reveal_all_normalized(tcx).and(*ty)) - .ok()? - .size; - val.try_to_bits(size) - } - Err(_) => None, - } - } - } - } - #[inline] pub fn try_eval_scalar( self, @@ -2434,8 +2385,23 @@ impl<'tcx> ConstantKind<'tcx> { } #[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() + pub fn try_eval_bits( + &self, + tcx: TyCtxt<'tcx>, + param_env: ty::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; + int.to_bits(size).ok() + } + + /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. + #[inline] + pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { + self.try_eval_bits(tcx, param_env, ty) + .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) } #[inline] @@ -2447,6 +2413,18 @@ impl<'tcx> ConstantKind<'tcx> { self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok() } + #[inline] + /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. + pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u64 { + self.try_eval_target_usize(tcx, param_env) + .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) + } + + #[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 from_value(val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self { Self::Val(val, ty) @@ -2586,7 +2564,7 @@ impl<'tcx> ConstantKind<'tcx> { } } - pub fn from_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self { match c.kind() { ty::ConstKind::Value(valtree) => { let const_val = tcx.valtree_to_const_val((c.ty(), valtree)); @@ -2899,7 +2877,7 @@ fn pretty_print_const_value<'tcx>( } } (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { - let n = n.try_to_bits(tcx.data_layout.pointer_size).unwrap(); + let n = n.try_to_target_usize(tcx).unwrap(); // cast is ok because we already checked for pointer size (32 or 64 bit) above let range = AllocRange { start: offset, size: Size::from_bytes(n) }; let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap(); diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 61e9000273f..86d1e463ed1 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -16,7 +16,6 @@ pub use int::*; pub use kind::*; use rustc_span::Span; use rustc_span::DUMMY_SP; -use rustc_target::abi::Size; pub use valtree::*; use super::sty::ConstKind; @@ -155,7 +154,7 @@ impl<'tcx> Const<'tcx> { let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic"); - match Self::try_eval_lit_or_param(tcx, ty, expr) { + match Self::try_from_lit_or_param(tcx, ty, expr) { Some(v) => v, None => ty::Const::new_unevaluated( tcx, @@ -169,7 +168,7 @@ impl<'tcx> Const<'tcx> { } #[instrument(skip(tcx), level = "debug")] - fn try_eval_lit_or_param( + fn try_from_lit_or_param( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>, @@ -244,14 +243,6 @@ impl<'tcx> Const<'tcx> { } } - /// Panics if self.kind != ty::ConstKind::Value - pub fn to_valtree(self) -> ty::ValTree<'tcx> { - match self.kind() { - ty::ConstKind::Value(valtree) => valtree, - _ => bug!("expected ConstKind::Value, got {:?}", self.kind()), - } - } - #[inline] /// Creates a constant with the given integer value and interns it. pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self { @@ -284,81 +275,6 @@ impl<'tcx> Const<'tcx> { Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) } - /// Attempts to convert to a `ValTree` - pub fn try_to_valtree(self) -> Option> { - match self.kind() { - ty::ConstKind::Value(valtree) => Some(valtree), - _ => None, - } - } - - #[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 - /// contains const generic parameters or pointers). - pub fn try_eval_bits( - self, - tcx: TyCtxt<'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 - int.to_bits(size).ok() - } - - #[inline] - pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - self.try_eval_scalar_int(tcx, param_env)?.try_into().ok() - } - - #[inline] - pub fn try_eval_target_usize( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option { - 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] - 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, - } - } - - #[inline] - /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. - pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { - self.try_eval_bits(tcx, param_env, ty) - .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) - } - - #[inline] - /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. - pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { - self.try_eval_target_usize(tcx, param_env) - .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) - } - /// Returns the evaluated constant pub fn eval( self, @@ -410,34 +326,106 @@ impl<'tcx> Const<'tcx> { } } + /// Normalizes the constant to a value or an error if possible. #[inline] - pub fn try_to_value(self) -> Option> { - if let ConstKind::Value(val) = self.kind() { Some(val) } else { None } + 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, + } + } + + #[inline] + 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] + /// 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.try_eval_scalar(tcx, param_env)?.try_to_int().ok() + } + + #[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_bits( + self, + tcx: TyCtxt<'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 + int.to_bits(size).ok() + } + + #[inline] + /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. + pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { + self.try_eval_bits(tcx, param_env, ty) + .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) + } + + #[inline] + pub fn try_eval_target_usize( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> Option { + self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok() + } + + #[inline] + pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { + self.try_eval_scalar_int(tcx, param_env)?.try_into().ok() + } + + #[inline] + /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. + pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { + self.try_eval_target_usize(tcx, param_env) + .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) + } + + /// Panics if self.kind != ty::ConstKind::Value + pub fn to_valtree(self) -> ty::ValTree<'tcx> { + match self.kind() { + ty::ConstKind::Value(valtree) => valtree, + _ => bug!("expected ConstKind::Value, got {:?}", self.kind()), + } + } + + /// Attempts to convert to a `ValTree` + pub fn try_to_valtree(self) -> Option> { + match self.kind() { + ty::ConstKind::Value(valtree) => Some(valtree), + _ => None, + } } #[inline] pub fn try_to_scalar(self) -> Option> { - self.try_to_value()?.try_to_scalar() - } - - #[inline] - pub fn try_to_scalar_int(self) -> Option { - self.try_to_value()?.try_to_scalar_int() - } - - #[inline] - pub fn try_to_bits(self, size: Size) -> Option { - self.try_to_scalar_int()?.to_bits(size).ok() - } - - #[inline] - pub fn try_to_bool(self) -> Option { - self.try_to_scalar_int()?.try_into().ok() + self.try_to_valtree()?.try_to_scalar() } #[inline] pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option { - self.try_to_value()?.try_to_target_usize(tcx) + self.try_to_valtree()?.try_to_target_usize(tcx) } pub fn is_ct_infer(self) -> bool { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index c184154eacf..0ea61ec8d40 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -198,11 +198,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } (Some(PatKind::Constant { value: lo }), None) => { let hi = ty.numeric_max_val(self.tcx)?; - Some((*lo, mir::ConstantKind::from_const(hi, self.tcx))) + Some((*lo, mir::ConstantKind::from_ty_const(hi, self.tcx))) } (None, Some(PatKind::Constant { value: hi })) => { let lo = ty.numeric_min_val(self.tcx)?; - Some((mir::ConstantKind::from_const(lo, self.tcx), *hi)) + Some((mir::ConstantKind::from_ty_const(lo, self.tcx), *hi)) } _ => None, } diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 8b0a0903d18..6e191b285be 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -136,7 +136,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { return; } - let literal = ConstantKind::from_const(len, self.tcx); + let literal = ConstantKind::from_ty_const(len, self.tcx); let constant = Constant { span: source_info.span, literal, user_ty: None }; *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); } diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index 6c3b7c58fab..1b846987d38 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -93,7 +93,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> { *rvalue = Rvalue::Use(Operand::Constant(Box::new(Constant { span: rustc_span::DUMMY_SP, user_ty: None, - literal: ConstantKind::from_const(len, self.tcx), + literal: ConstantKind::from_ty_const(len, self.tcx), }))); } self.super_rvalue(rvalue, loc); diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 3a33568084c..2fc102bda13 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -230,7 +230,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { self.write_str("[")?; self = self.print_type(ty)?; self.write_str("; ")?; - if let Some(size) = size.try_to_bits(self.tcx().data_layout.pointer_size) { + if let Some(size) = size.try_to_target_usize(self.tcx()) { write!(self, "{size}")? } else if let ty::ConstKind::Param(param) = size.kind() { self = param.print(self)? diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 0e73bad1918..fe71a9f07df 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -257,7 +257,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]` if let ty::Array(aty, len) = self_ty.kind() { flags.push((sym::_Self, Some("[]".to_string()))); - let len = len.try_to_value().and_then(|v| v.try_to_target_usize(self.tcx)); + let len = len.try_to_valtree().and_then(|v| v.try_to_target_usize(self.tcx)); flags.push((sym::_Self, Some(format!("[{aty}; _]")))); if let Some(n) = len { flags.push((sym::_Self, Some(format!("[{aty}; {n}]")))); diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs index 8be3c178a29..6e13148f2fc 100644 --- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs @@ -37,22 +37,14 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) Some(lhs) => constant(cx, cx.typeck_results(), lhs)?, None => { let min_val_const = ty.numeric_min_val(cx.tcx)?; - let min_constant = mir::ConstantKind::from_value( - cx.tcx.valtree_to_const_val((ty, min_val_const.to_valtree())), - ty, - ); - miri_to_const(cx, min_constant)? + miri_to_const(cx, mir::ConstantKind::from_ty_const(min_val_const, cx.tcx))? }, }; let rhs_const = match rhs { Some(rhs) => constant(cx, cx.typeck_results(), rhs)?, None => { let max_val_const = ty.numeric_max_val(cx.tcx)?; - let max_constant = mir::ConstantKind::from_value( - cx.tcx.valtree_to_const_val((ty, max_val_const.to_valtree())), - ty, - ); - miri_to_const(cx, max_constant)? + miri_to_const(cx, mir::ConstantKind::from_ty_const(max_val_const, cx.tcx))? }, }; let lhs_val = lhs_const.int_value(cx, ty)?;