restore the old logic adjusting ty::UnevaluatedConst before evaluation
This commit is contained in:
parent
11a4a24d8e
commit
8ef6b7a417
@ -2336,18 +2336,19 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Option<Span>,
|
||||
) -> Result<interpret::ConstValue<'tcx>, ErrorHandled> {
|
||||
let uneval = match self {
|
||||
let (uneval, param_env) = match self {
|
||||
ConstantKind::Ty(c) => {
|
||||
if let ty::ConstKind::Unevaluated(uv) = c.kind() {
|
||||
if let ty::ConstKind::Unevaluated(uneval) = c.kind() {
|
||||
// Avoid the round-trip via valtree, evaluate directly to ConstValue.
|
||||
uv.expand()
|
||||
let (param_env, uneval) = uneval.prepare_for_eval(tcx, param_env);
|
||||
(uneval.expand(), param_env)
|
||||
} else {
|
||||
// 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)));
|
||||
}
|
||||
}
|
||||
ConstantKind::Unevaluated(uneval, _) => uneval,
|
||||
ConstantKind::Unevaluated(uneval, _) => (uneval, param_env),
|
||||
ConstantKind::Val(val, _) => return Ok(val),
|
||||
};
|
||||
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
|
||||
|
@ -276,6 +276,7 @@ impl<'tcx> Const<'tcx> {
|
||||
}
|
||||
|
||||
/// Returns the evaluated constant
|
||||
#[inline]
|
||||
pub fn eval(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
@ -285,32 +286,9 @@ impl<'tcx> Const<'tcx> {
|
||||
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
|
||||
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) 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();
|
||||
let (param_env, unevaluated) = unevaluated.prepare_for_eval(tcx, param_env);
|
||||
// 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)?;
|
||||
|
@ -2,7 +2,7 @@ use super::Const;
|
||||
use crate::mir;
|
||||
use crate::ty::abstract_const::CastKind;
|
||||
use crate::ty::GenericArgsRef;
|
||||
use crate::ty::{self, List, Ty};
|
||||
use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::HashStable;
|
||||
@ -26,6 +26,39 @@ impl<'tcx> UnevaluatedConst<'tcx> {
|
||||
pub fn expand(self) -> mir::UnevaluatedConst<'tcx> {
|
||||
mir::UnevaluatedConst { def: self.def, args: self.args, promoted: None }
|
||||
}
|
||||
|
||||
/// FIXME(RalfJung): I cannot explain what this does or why it makes sense, but not doing this
|
||||
/// hurts performance.
|
||||
#[inline]
|
||||
pub(crate) fn prepare_for_eval(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> (ty::ParamEnv<'tcx>, Self) {
|
||||
// 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.
|
||||
if (param_env, self).has_non_region_infer() {
|
||||
(
|
||||
tcx.param_env(self.def),
|
||||
ty::UnevaluatedConst {
|
||||
def: self.def,
|
||||
args: ty::GenericArgs::identity_for_item(tcx, self.def),
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(tcx.erase_regions(param_env).with_reveal_all_normalized(tcx), tcx.erase_regions(self))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UnevaluatedConst<'tcx> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user