diff options
| author | bors <bors@rust-lang.org> | 2022-05-18 20:12:07 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-05-18 20:12:07 +0000 |
| commit | cd282d7f75da9080fda0f1740a729516e7fbec68 (patch) | |
| tree | 7e55bf30bbcb3318fd38faec8a3490506d1bf4f8 /compiler/rustc_const_eval/src | |
| parent | 07ae142d77f56dd48f2736605e0a6c015f2aecc6 (diff) | |
| parent | 96b36d6eb21daaca2c2d04fd8d7c27bef5eb90c6 (diff) | |
| download | rust-cd282d7f75da9080fda0f1740a729516e7fbec68.tar.gz rust-cd282d7f75da9080fda0f1740a729516e7fbec68.zip | |
Auto merge of #97019 - b-naber:transition-to-valtrees-pt1, r=oli-obk
Transition to valtrees pt1 Compartmentalising https://github.com/rust-lang/rust/pull/96591 as much as possible. r? `@oli-obk`
Diffstat (limited to 'compiler/rustc_const_eval/src')
| -rw-r--r-- | compiler/rustc_const_eval/src/const_eval/eval_queries.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/const_eval/mod.rs | 130 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/const_eval/valtrees.rs | 143 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/place.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/lib.rs | 22 |
5 files changed, 236 insertions, 81 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 5c56e6ee5f5..d7cbc48e032 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -135,7 +135,7 @@ pub(super) fn op_to_const<'tcx>( } else { // It is guaranteed that any non-slice scalar pair is actually ByRef here. // When we come back from raw const eval, we are always by-ref. The only way our op here is - // by-val is if we are in destructure_const, i.e., if this is (a field of) something that we + // by-val is if we are in destructure_mir_constant, i.e., if this is (a field of) something that we // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or // structs containing such. op.try_as_mplace() diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 96c18d488ee..db43f7a425c 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -4,6 +4,7 @@ use std::convert::TryFrom; use rustc_hir::Mutability; use rustc_middle::mir; +use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{source_map::DUMMY_SP, symbol::Symbol}; @@ -22,7 +23,7 @@ pub use error::*; pub use eval_queries::*; pub use fn_queries::*; pub use machine::*; -pub(crate) use valtrees::{const_to_valtree, valtree_to_const_value}; +pub(crate) use valtrees::{const_to_valtree_inner, valtree_to_const_value}; pub(crate) fn const_caller_location( tcx: TyCtxt<'_>, @@ -38,6 +39,57 @@ pub(crate) fn const_caller_location( ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr, &tcx)) } +// We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes. +const VALTREE_MAX_NODES: usize = 1000; + +pub(crate) enum ValTreeCreationError { + NodesOverflow, + NonSupportedType, + Other, +} +pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>; + +/// Evaluates a constant and turns it into a type-level constant value. +pub(crate) fn eval_to_valtree<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + cid: GlobalId<'tcx>, +) -> EvalToValTreeResult<'tcx> { + let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?; + let ecx = mk_eval_cx( + tcx, DUMMY_SP, param_env, + // It is absolutely crucial for soundness that + // we do not read from static items or other mutable memory. + false, + ); + let place = ecx.raw_const_to_mplace(const_alloc).unwrap(); + debug!(?place); + + let mut num_nodes = 0; + let valtree_result = const_to_valtree_inner(&ecx, &place, &mut num_nodes); + + match valtree_result { + Ok(valtree) => Ok(Some(valtree)), + Err(err) => { + let did = cid.instance.def_id(); + let s = cid.display(tcx); + match err { + ValTreeCreationError::NodesOverflow => { + let msg = format!("maximum number of nodes exceeded in constant {}", &s); + let mut diag = match tcx.hir().span_if_local(did) { + Some(span) => tcx.sess.struct_span_err(span, &msg), + None => tcx.sess.struct_err(&msg), + }; + diag.emit(); + + Ok(None) + } + ValTreeCreationError::NonSupportedType | ValTreeCreationError::Other => Ok(None), + } + } + } +} + /// This function should never fail for validated constants. However, it is also invoked from the /// pretty printer which might attempt to format invalid constants and in that case it might fail. pub(crate) fn try_destructure_const<'tcx>( @@ -48,7 +100,6 @@ pub(crate) fn try_destructure_const<'tcx>( trace!("destructure_const: {:?}", val); let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); let op = ecx.const_to_op(val, None)?; - // We go to `usize` as we cannot allocate anything bigger anyway. let (field_count, variant, down) = match val.ty().kind() { ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op), @@ -64,7 +115,6 @@ pub(crate) fn try_destructure_const<'tcx>( ty::Tuple(substs) => (substs.len(), None, op), _ => bug!("cannot destructure constant {:?}", val), }; - let fields = (0..field_count) .map(|i| { let field_op = ecx.operand_field(&down, i)?; @@ -73,11 +123,47 @@ pub(crate) fn try_destructure_const<'tcx>( }) .collect::<InterpResult<'tcx, Vec<_>>>()?; let fields = tcx.arena.alloc_from_iter(fields); - Ok(mir::DestructuredConst { variant, fields }) } #[instrument(skip(tcx), level = "debug")] +pub(crate) fn try_destructure_mir_constant<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + val: mir::ConstantKind<'tcx>, +) -> InterpResult<'tcx, mir::DestructuredMirConstant<'tcx>> { + trace!("destructure_mir_constant: {:?}", val); + let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); + let op = ecx.mir_const_to_op(&val, None)?; + + // We go to `usize` as we cannot allocate anything bigger anyway. + let (field_count, variant, down) = match val.ty().kind() { + ty::Array(_, len) => (len.eval_usize(tcx, param_env) as usize, None, op), + ty::Adt(def, _) if def.variants().is_empty() => { + throw_ub!(Unreachable) + } + ty::Adt(def, _) => { + let variant = ecx.read_discriminant(&op).unwrap().1; + let down = ecx.operand_downcast(&op, variant).unwrap(); + (def.variants()[variant].fields.len(), Some(variant), down) + } + ty::Tuple(substs) => (substs.len(), None, op), + _ => bug!("cannot destructure mir constant {:?}", val), + }; + + let fields_iter = (0..field_count) + .map(|i| { + let field_op = ecx.operand_field(&down, i)?; + let val = op_to_const(&ecx, &field_op); + Ok(mir::ConstantKind::Val(val, field_op.layout.ty)) + }) + .collect::<InterpResult<'tcx, Vec<_>>>()?; + let fields = tcx.arena.alloc_from_iter(fields_iter); + + Ok(mir::DestructuredMirConstant { variant, fields }) +} + +#[instrument(skip(tcx), level = "debug")] pub(crate) fn deref_const<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -113,3 +199,39 @@ pub(crate) fn deref_const<'tcx>( tcx.mk_const(ty::ConstS { val: ty::ConstKind::Value(op_to_const(&ecx, &mplace.into())), ty }) } + +#[instrument(skip(tcx), level = "debug")] +pub(crate) fn deref_mir_constant<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + val: mir::ConstantKind<'tcx>, +) -> mir::ConstantKind<'tcx> { + let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); + let op = ecx.mir_const_to_op(&val, None).unwrap(); + let mplace = ecx.deref_operand(&op).unwrap(); + if let Some(alloc_id) = mplace.ptr.provenance { + assert_eq!( + tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().0.0.mutability, + Mutability::Not, + "deref_const cannot be used with mutable allocations as \ + that could allow pattern matching to observe mutable statics", + ); + } + + let ty = match mplace.meta { + MemPlaceMeta::None => mplace.layout.ty, + MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace), + // In case of unsized types, figure out the real type behind. + MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() { + ty::Str => bug!("there's no sized equivalent of a `str`"), + ty::Slice(elem_ty) => tcx.mk_array(*elem_ty, scalar.to_machine_usize(&tcx).unwrap()), + _ => bug!( + "type {} should not have metadata, but had {:?}", + mplace.layout.ty, + mplace.meta + ), + }, + }; + + mir::ConstantKind::Val(op_to_const(&ecx, &mplace.into()), ty) +} diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index f57f25c19f9..7346d69bb5d 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -1,33 +1,16 @@ use super::eval_queries::{mk_eval_cx, op_to_const}; use super::machine::CompileTimeEvalContext; +use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES}; use crate::interpret::{ intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta, MemoryKind, PlaceTy, Scalar, ScalarMaybeUninit, }; -use rustc_middle::mir::interpret::ConstAlloc; -use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_span::source_map::DUMMY_SP; use rustc_target::abi::{Align, VariantIdx}; use crate::interpret::MPlaceTy; use crate::interpret::Value; - -/// Convert an evaluated constant to a type level constant -#[instrument(skip(tcx), level = "debug")] -pub(crate) fn const_to_valtree<'tcx>( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - raw: ConstAlloc<'tcx>, -) -> Option<ty::ValTree<'tcx>> { - let ecx = mk_eval_cx( - tcx, DUMMY_SP, param_env, - // It is absolutely crucial for soundness that - // we do not read from static items or other mutable memory. - false, - ); - let place = ecx.raw_const_to_mplace(raw).unwrap(); - const_to_valtree_inner(&ecx, &place) -} +use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; #[instrument(skip(ecx), level = "debug")] fn branches<'tcx>( @@ -35,7 +18,8 @@ fn branches<'tcx>( place: &MPlaceTy<'tcx>, n: usize, variant: Option<VariantIdx>, -) -> Option<ty::ValTree<'tcx>> { + num_nodes: &mut usize, +) -> ValTreeCreationResult<'tcx> { let place = match variant { Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(), None => *place, @@ -43,82 +27,116 @@ fn branches<'tcx>( let variant = variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32())))); debug!(?place, ?variant); - let fields = (0..n).map(|i| { + let mut fields = Vec::with_capacity(n); + for i in 0..n { let field = ecx.mplace_field(&place, i).unwrap(); - const_to_valtree_inner(ecx, &field) - }); - // For enums, we preped their variant index before the variant's fields so we can figure out + let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?; + fields.push(Some(valtree)); + } + + // For enums, we prepend their variant index before the variant's fields so we can figure out // the variant again when just seeing a valtree. - let branches = variant.into_iter().chain(fields); - Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?))) + let branches = variant + .into_iter() + .chain(fields.into_iter()) + .collect::<Option<Vec<_>>>() + .expect("should have already checked for errors in ValTree creation"); + + // Have to account for ZSTs here + if branches.len() == 0 { + *num_nodes += 1; + } + + Ok(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches))) } #[instrument(skip(ecx), level = "debug")] fn slice_branches<'tcx>( ecx: &CompileTimeEvalContext<'tcx, 'tcx>, place: &MPlaceTy<'tcx>, -) -> Option<ty::ValTree<'tcx>> { + num_nodes: &mut usize, +) -> ValTreeCreationResult<'tcx> { let n = place .len(&ecx.tcx.tcx) .unwrap_or_else(|_| panic!("expected to use len of place {:?}", place)); - let branches = (0..n).map(|i| { + + let mut elems = Vec::with_capacity(n as usize); + for i in 0..n { let place_elem = ecx.mplace_index(place, i).unwrap(); - const_to_valtree_inner(ecx, &place_elem) - }); + let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes)?; + elems.push(valtree); + } - Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?))) + Ok(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(elems))) } #[instrument(skip(ecx), level = "debug")] -fn const_to_valtree_inner<'tcx>( +pub(crate) fn const_to_valtree_inner<'tcx>( ecx: &CompileTimeEvalContext<'tcx, 'tcx>, place: &MPlaceTy<'tcx>, -) -> Option<ty::ValTree<'tcx>> { - match place.layout.ty.kind() { - ty::FnDef(..) => Some(ty::ValTree::zst()), + num_nodes: &mut usize, +) -> ValTreeCreationResult<'tcx> { + if *num_nodes >= VALTREE_MAX_NODES { + return Err(ValTreeCreationError::NodesOverflow); + } + + let ty = place.layout.ty; + debug!("ty kind: {:?}", ty.kind()); + + match ty.kind() { + ty::FnDef(..) => { + *num_nodes += 1; + Ok(ty::ValTree::zst()) + } ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => { - let val = ecx.read_immediate(&place.into()).unwrap(); + let Ok(val) = ecx.read_immediate(&place.into()) else { + return Err(ValTreeCreationError::Other); + }; let val = val.to_scalar().unwrap(); - Some(ty::ValTree::Leaf(val.assert_int())) + *num_nodes += 1; + + Ok(ty::ValTree::Leaf(val.assert_int())) } // Raw pointers are not allowed in type level constants, as we cannot properly test them for // equality at compile-time (see `ptr_guaranteed_eq`/`_ne`). // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to // agree with runtime equality tests. - ty::FnPtr(_) | ty::RawPtr(_) => None, + ty::FnPtr(_) | ty::RawPtr(_) => Err(ValTreeCreationError::NonSupportedType), ty::Ref(_, _, _) => { - let derefd_place = ecx.deref_operand(&place.into()).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e)); + let Ok(derefd_place)= ecx.deref_operand(&place.into()) else { + return Err(ValTreeCreationError::Other); + }; debug!(?derefd_place); - const_to_valtree_inner(ecx, &derefd_place) + const_to_valtree_inner(ecx, &derefd_place, num_nodes) } ty::Str | ty::Slice(_) | ty::Array(_, _) => { - let valtree = slice_branches(ecx, place); - debug!(?valtree); - - valtree + slice_branches(ecx, place, num_nodes) } // Trait objects are not allowed in type level constants, as we have no concept for // resolving their backing type, even if we can do that at const eval time. We may // hypothetically be able to allow `dyn StructuralEq` trait objects in the future, // but it is unclear if this is useful. - ty::Dynamic(..) => None, + ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType), - ty::Tuple(substs) => branches(ecx, place, substs.len(), None), + ty::Tuple(elem_tys) => { + branches(ecx, place, elem_tys.len(), None, num_nodes) + } ty::Adt(def, _) => { if def.is_union() { - return None + return Err(ValTreeCreationError::NonSupportedType); } else if def.variants().is_empty() { bug!("uninhabited types should have errored and never gotten converted to valtree") } - let variant = ecx.read_discriminant(&place.into()).unwrap().1; - - branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant)) + let Ok((_, variant)) = ecx.read_discriminant(&place.into()) else { + return Err(ValTreeCreationError::Other); + }; + branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes) } ty::Never @@ -136,7 +154,7 @@ fn const_to_valtree_inner<'tcx>( // FIXME(oli-obk): we can probably encode closures just like structs | ty::Closure(..) | ty::Generator(..) - | ty::GeneratorWitness(..) => None, + | ty::GeneratorWitness(..) => Err(ValTreeCreationError::NonSupportedType), } } @@ -225,8 +243,11 @@ fn create_pointee_place<'tcx>( .unwrap(); debug!(?ptr); - let mut place = MPlaceTy::from_aligned_ptr(ptr.into(), layout); - place.meta = MemPlaceMeta::Meta(Scalar::from_u64(num_elems as u64)); + let place = MPlaceTy::from_aligned_ptr_with_meta( + ptr.into(), + layout, + MemPlaceMeta::Meta(Scalar::from_u64(num_elems as u64)), + ); debug!(?place); place @@ -237,11 +258,11 @@ fn create_pointee_place<'tcx>( /// Converts a `ValTree` to a `ConstValue`, which is needed after mir /// construction has finished. -// FIXME Merge `valtree_to_const_value` and `fill_place_recursively` into one function +// FIXME Merge `valtree_to_const_value` and `valtree_into_mplace` into one function #[instrument(skip(tcx), level = "debug")] pub fn valtree_to_const_value<'tcx>( tcx: TyCtxt<'tcx>, - param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + ty: Ty<'tcx>, valtree: ty::ValTree<'tcx>, ) -> ConstValue<'tcx> { // Basic idea: We directly construct `Scalar` values from trivial `ValTree`s @@ -251,8 +272,8 @@ pub fn valtree_to_const_value<'tcx>( // create inner `MPlace`s which are filled recursively. // FIXME Does this need an example? - let (param_env, ty) = param_env_ty.into_parts(); - let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); + let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::empty(), false); + let param_env_ty = ty::ParamEnv::empty().and(ty); match ty.kind() { ty::FnDef(..) => { @@ -275,7 +296,7 @@ pub fn valtree_to_const_value<'tcx>( }; debug!(?place); - fill_place_recursively(&mut ecx, &mut place, valtree); + valtree_into_mplace(&mut ecx, &mut place, valtree); dump_place(&ecx, place.into()); intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &place).unwrap(); @@ -317,7 +338,7 @@ pub fn valtree_to_const_value<'tcx>( // FIXME Needs a better/correct name #[instrument(skip(ecx), level = "debug")] -fn fill_place_recursively<'tcx>( +fn valtree_into_mplace<'tcx>( ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>, place: &mut MPlaceTy<'tcx>, valtree: ty::ValTree<'tcx>, @@ -349,7 +370,7 @@ fn fill_place_recursively<'tcx>( let mut pointee_place = create_pointee_place(ecx, *inner_ty, valtree); debug!(?pointee_place); - fill_place_recursively(ecx, &mut pointee_place, valtree); + valtree_into_mplace(ecx, &mut pointee_place, valtree); dump_place(ecx, pointee_place.into()); intern_const_alloc_recursive(ecx, InternKind::Constant, &pointee_place).unwrap(); @@ -437,7 +458,7 @@ fn fill_place_recursively<'tcx>( }; debug!(?place_inner); - fill_place_recursively(ecx, &mut place_inner, *inner_valtree); + valtree_into_mplace(ecx, &mut place_inner, *inner_valtree); dump_place(&ecx, place_inner.into()); } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 95d6f431391..62f9c8f990d 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -115,12 +115,6 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for MPlaceTy<'tcx, Tag> { } } -impl<'tcx, Tag: Provenance> std::ops::DerefMut for MPlaceTy<'tcx, Tag> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.mplace - } -} - impl<'tcx, Tag: Provenance> From<MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> { #[inline(always)] fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self { @@ -197,6 +191,18 @@ impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> { } #[inline] + pub fn from_aligned_ptr_with_meta( + ptr: Pointer<Option<Tag>>, + layout: TyAndLayout<'tcx>, + meta: MemPlaceMeta<Tag>, + ) -> Self { + let mut mplace = MemPlace::from_ptr(ptr, layout.align.abi); + mplace.meta = meta; + + MPlaceTy { mplace, layout } + } + + #[inline] pub(crate) fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> { if self.layout.is_unsized() { // We need to consult `meta` metadata @@ -495,7 +501,7 @@ where /// Project into an mplace #[instrument(skip(self), level = "debug")] - pub(crate) fn mplace_projection( + pub(super) fn mplace_projection( &self, base: &MPlaceTy<'tcx, M::PointerTag>, proj_elem: mir::PlaceElem<'tcx>, diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 1ab461a9421..8b6689ca213 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -34,26 +34,32 @@ pub mod transform; pub mod util; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::ParamEnv; pub fn provide(providers: &mut Providers) { const_eval::provide(providers); providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider; providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider; providers.const_caller_location = const_eval::const_caller_location; - providers.try_destructure_const = |tcx, param_env_and_value| { - let (param_env, value) = param_env_and_value.into_parts(); - const_eval::try_destructure_const(tcx, param_env, value).ok() + providers.try_destructure_const = |tcx, param_env_and_val| { + let (param_env, c) = param_env_and_val.into_parts(); + const_eval::try_destructure_const(tcx, param_env, c).ok() }; - providers.const_to_valtree = |tcx, param_env_and_value| { + providers.eval_to_valtree = |tcx, param_env_and_value| { let (param_env, raw) = param_env_and_value.into_parts(); - const_eval::const_to_valtree(tcx, param_env, raw) + const_eval::eval_to_valtree(tcx, param_env, raw) }; - providers.valtree_to_const_val = |tcx, (ty, valtree)| { - const_eval::valtree_to_const_value(tcx, ParamEnv::empty().and(ty), valtree) + providers.try_destructure_mir_constant = |tcx, param_env_and_value| { + let (param_env, value) = param_env_and_value.into_parts(); + const_eval::try_destructure_mir_constant(tcx, param_env, value).ok() }; + providers.valtree_to_const_val = + |tcx, (ty, valtree)| const_eval::valtree_to_const_value(tcx, ty, valtree); providers.deref_const = |tcx, param_env_and_value| { let (param_env, value) = param_env_and_value.into_parts(); const_eval::deref_const(tcx, param_env, value) }; + providers.deref_mir_constant = |tcx, param_env_and_value| { + let (param_env, value) = param_env_and_value.into_parts(); + const_eval::deref_mir_constant(tcx, param_env, value) + }; } |
