diff options
| author | Michael Goulet <michael@errs.io> | 2024-09-27 12:56:51 -0400 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2024-10-19 18:07:35 +0000 |
| commit | e83e4e81123ea2babc04238d5aca01ec4bf3e763 (patch) | |
| tree | 82f61bf363145172ca403449b4f76fb0c0524ac4 /compiler/rustc_middle/src | |
| parent | a2a1206811d864df2bb61b2fc27ddc45a3589424 (diff) | |
| download | rust-e83e4e81123ea2babc04238d5aca01ec4bf3e763.tar.gz rust-e83e4e81123ea2babc04238d5aca01ec4bf3e763.zip | |
Get rid of const eval_* and try_eval_* helpers
Diffstat (limited to 'compiler/rustc_middle/src')
| -rw-r--r-- | compiler/rustc_middle/src/mir/consts.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/tcx.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/consts.rs | 132 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/layout.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 7 |
6 files changed, 53 insertions, 108 deletions
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 4262460d928..1be2f6b9bb5 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -6,6 +6,7 @@ use rustc_session::RemapFileNameExt; use rustc_session::config::RemapPathScopeComponents; use rustc_span::{DUMMY_SP, Span}; use rustc_target::abi::{HasDataLayout, Size}; +use either::Either; use crate::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, Scalar, alloc_range}; use crate::mir::{Promoted, pretty_print_const_value}; @@ -320,8 +321,14 @@ impl<'tcx> Const<'tcx> { Const::Ty(_, c) => { // We want to consistently have a "clean" value for type system constants (i.e., no // data hidden in the padding), so we always go through a valtree here. - let (ty, val) = c.eval(tcx, param_env, span)?; - Ok(tcx.valtree_to_const_val((ty, val))) + match c.eval_valtree(tcx, param_env, span) { + Ok((ty, val)) => Ok(tcx.valtree_to_const_val((ty, val))), + Err(Either::Left(_bad_ty)) => Err(tcx + .dcx() + .delayed_bug("`mir::Const::eval` called on a non-valtree-compatible type") + .into()), + Err(Either::Right(e)) => Err(e), + } } Const::Unevaluated(uneval, _) => { // FIXME: We might want to have a `try_eval`-like function on `Unevaluated` diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 8d57d0d8654..476e352ed92 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -55,7 +55,7 @@ impl<'tcx> PlaceTy<'tcx> { /// `PlaceElem`, where we can just use the `Ty` that is already /// stored inline on field projection elems. pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> { - self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty, |_, ty| ty) + self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty) } /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })` @@ -66,7 +66,6 @@ impl<'tcx> PlaceTy<'tcx> { pub fn projection_ty_core<V, T>( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, elem: &ProjectionElem<V, T>, mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>, mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>, @@ -93,7 +92,9 @@ impl<'tcx> PlaceTy<'tcx> { ty::Slice(..) => self.ty, ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from), ty::Array(inner, size) if from_end => { - let size = size.eval_target_usize(tcx, param_env); + let size = size + .try_to_target_usize(tcx) + .expect("expected subslice projection on fixed-size array"); let len = size - from - to; Ty::new_array(tcx, *inner, len) } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 389d20f315f..c0cd79e9ef2 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -398,133 +398,65 @@ impl<'tcx> Const<'tcx> { } } - /// Returns the evaluated constant - #[inline] - pub fn eval( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - span: Span, - ) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> { - self.eval_valtree(tcx, param_env, span).map_err(|err| { - match err { - Either::Right(err) => err, - Either::Left(_bad_ty) => { - // This can happen when we run on ill-typed code. - let e = tcx.dcx().span_delayed_bug( - span, - "`ty::Const::eval` called on a non-valtree-compatible type", - ); - e.into() - } - } - }) - } - /// 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, DUMMY_SP) { + match self.eval_valtree(tcx, param_env, DUMMY_SP) { Ok((ty, val)) => Self::new_value(tcx, val, ty), - Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into()), - Err(ErrorHandled::TooGeneric(_span)) => self, + Err(Either::Left(_bad_ty)) => { + // This can happen when we run on ill-typed code. + Self::new_error( + tcx, + tcx.dcx() + .delayed_bug("`ty::Const::eval` called on a non-valtree-compatible type"), + ) + } + Err(Either::Right(ErrorHandled::Reported(r, _span))) => Self::new_error(tcx, r.into()), + Err(Either::Right(ErrorHandled::TooGeneric(_span))) => self, } } - #[inline] - pub fn try_eval_scalar( - self, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Option<(Ty<'tcx>, Scalar)> { - let (ty, val) = self.eval(tcx, param_env, DUMMY_SP).ok()?; - let val = val.try_to_scalar()?; - Some((ty, val)) - } - - #[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<(Ty<'tcx>, ScalarInt)> { - let (ty, scalar) = self.try_eval_scalar(tcx, param_env)?; - let val = scalar.try_to_scalar_int().ok()?; - Some((ty, val)) - } - - #[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>) -> Option<u128> { - let (ty, scalar) = self.try_eval_scalar_int(tcx, param_env)?; - 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 - Some(scalar.to_bits(size)) - } - - #[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>) -> u128 { - self.try_eval_bits(tcx, param_env) - .unwrap_or_else(|| bug!("failed to evalate {:#?} to bits", self)) - } - - #[inline] - pub fn try_eval_target_usize( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option<u64> { - let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?; - Some(scalar.to_target_usize(tcx)) - } - - #[inline] - pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> { - let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?; - scalar.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> { + pub fn to_valtree(self) -> (ty::ValTree<'tcx>, Ty<'tcx>) { match self.kind() { - ty::ConstKind::Value(_, valtree) => valtree, + ty::ConstKind::Value(ty, valtree) => (valtree, ty), _ => bug!("expected ConstKind::Value, got {:?}", self.kind()), } } /// Attempts to convert to a `ValTree` - pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> { + pub fn try_to_valtree(self) -> Option<(ty::ValTree<'tcx>, Ty<'tcx>)> { match self.kind() { - ty::ConstKind::Value(_, valtree) => Some(valtree), + ty::ConstKind::Value(ty, valtree) => Some((valtree, ty)), _ => None, } } #[inline] - pub fn try_to_scalar(self) -> Option<Scalar> { - self.try_to_valtree()?.try_to_scalar() + pub fn try_to_scalar(self) -> Option<(Scalar, Ty<'tcx>)> { + let (valtree, ty) = self.try_to_valtree()?; + Some((valtree.try_to_scalar()?, ty)) } pub fn try_to_bool(self) -> Option<bool> { - self.try_to_valtree()?.try_to_scalar_int()?.try_to_bool().ok() + self.try_to_valtree()?.0.try_to_scalar_int()?.try_to_bool().ok() } #[inline] pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { - self.try_to_valtree()?.try_to_target_usize(tcx) + self.try_to_valtree()?.0.try_to_target_usize(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_to_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> { + let (scalar, ty) = self.try_to_scalar()?; + let scalar = scalar.try_to_scalar_int().ok()?; + 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 + Some(scalar.to_bits(size)) } pub fn is_ct_infer(self) -> bool { diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index 54b8507babf..bf741f63a3d 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -85,7 +85,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { match self { Self::False => Ok(false), Self::True => Ok(true), - Self::ConstIsZero(const_) => match const_.try_eval_target_usize(tcx, param_env) { + Self::ConstIsZero(const_) => match const_.try_to_target_usize(tcx) { None | Some(0) => Ok(true), Some(1..) => Ok(false), }, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 6c12b691c26..3670b6bbc77 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -397,7 +397,7 @@ impl<'tcx> SizeSkeleton<'tcx> { } } ty::Array(inner, len) if tcx.features().transmute_generic_consts => { - let len_eval = len.try_eval_target_usize(tcx, param_env); + let len_eval = len.try_to_target_usize(tcx); if len_eval == Some(0) { return Ok(SizeSkeleton::Known(Size::from_bytes(0), None)); } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 3f00458d195..74de378c4d7 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1117,7 +1117,12 @@ impl<'tcx> Ty<'tcx> { // The way we evaluate the `N` in `[T; N]` here only works since we use // `simd_size_and_type` post-monomorphization. It will probably start to ICE // if we use it in generic code. See the `simd-array-trait` ui test. - (f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty) + ( + f0_len + .try_to_target_usize(tcx) + .expect("expected SIMD field to have definite array size"), + *f0_elem_ty, + ) } #[inline] |
