diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 5cc1fa2a497..900adb559bd 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -6,7 +6,7 @@ }; use rustc_middle::mir; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{source_map::DUMMY_SP, symbol::Symbol}; mod error; @@ -89,14 +89,15 @@ pub(crate) fn eval_to_valtree<'tcx>( #[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>, + val: ConstValue<'tcx>, + ty: Ty<'tcx>, ) -> InterpResult<'tcx, mir::DestructuredConstant<'tcx>> { + let param_env = ty::ParamEnv::reveal_all(); let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No); - let op = ecx.eval_mir_constant(&val, None, None)?; + let op = ecx.const_val_to_op(val, ty, None)?; // We go to `usize` as we cannot allocate anything bigger anyway. - let (field_count, variant, down) = match val.ty().kind() { + let (field_count, variant, down) = match ty.kind() { ty::Array(_, len) => (len.eval_target_usize(tcx, param_env) as usize, None, op), ty::Adt(def, _) if def.variants().is_empty() => { throw_ub!(Unreachable) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index e30af165501..ba3be9083be 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -633,7 +633,7 @@ pub fn eval_mir_constant( } } - pub(super) fn const_val_to_op( + pub(crate) fn const_val_to_op( &self, val_val: ConstValue<'tcx>, ty: Ty<'tcx>, diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 8314f53ba57..826d2a15721 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -52,10 +52,8 @@ pub fn provide(providers: &mut Providers) { let (param_env, raw) = param_env_and_value.into_parts(); const_eval::eval_to_valtree(tcx, param_env, raw) }; - 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.try_destructure_mir_constant = + |tcx, (cv, ty)| const_eval::try_destructure_mir_constant(tcx, cv, ty).ok(); providers.valtree_to_const_val = |tcx, (ty, valtree)| { const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree) }; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 124b5692048..af244d870c0 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2882,15 +2882,10 @@ fn pretty_print_const_value<'tcx>( // introducing ICEs (e.g. via `layout_of`) from missing bounds. // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized` // to be able to destructure the tuple into `(0u8, *mut T)` - // - // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the - // correct `ty::ParamEnv` to allow printing *all* constant values. (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => { let ct = tcx.lift(ct).unwrap(); let ty = tcx.lift(ty).unwrap(); - if let Some(contents) = tcx.try_destructure_mir_constant( - ty::ParamEnv::reveal_all().and(ConstantKind::Val(ct, ty)), - ) { + if let Some(contents) = tcx.try_destructure_mir_constant((ct, ty)) { let fields = contents.fields.to_vec(); match *ty.kind() { ty::Array(..) => { diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 4006a6cd1cc..0119e07a44e 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -2,6 +2,7 @@ use crate::infer::canonical::Canonical; use crate::mir; +use crate::mir::interpret::ConstValue; use crate::traits; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::{TyAndLayout, ValidityRequirement}; @@ -333,6 +334,14 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span { } } +impl<'tcx> Key for (ConstValue<'tcx>, Ty<'tcx>) { + type CacheSelector = DefaultCacheSelector; + + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> { type CacheSelector = DefaultCacheSelector; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0e1c6d19e31..81efbd8b094 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1087,11 +1087,13 @@ } /// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index - /// and its field values. + /// and its field values. This should only be used for pretty printing. query try_destructure_mir_constant( - key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> + key: (ConstValue<'tcx>, Ty<'tcx>) ) -> Option> { desc { "destructuring MIR constant"} + no_hash + eval_always } query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {