Skip to content

Commit 8ef6b7a

Browse files
committed
restore the old logic adjusting ty::UnevaluatedConst before evaluation
1 parent 11a4a24 commit 8ef6b7a

File tree

3 files changed

+41
-29
lines changed

3 files changed

+41
-29
lines changed

compiler/rustc_middle/src/mir/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -2336,18 +2336,19 @@ impl<'tcx> ConstantKind<'tcx> {
23362336
param_env: ty::ParamEnv<'tcx>,
23372337
span: Option<Span>,
23382338
) -> Result<interpret::ConstValue<'tcx>, ErrorHandled> {
2339-
let uneval = match self {
2339+
let (uneval, param_env) = match self {
23402340
ConstantKind::Ty(c) => {
2341-
if let ty::ConstKind::Unevaluated(uv) = c.kind() {
2341+
if let ty::ConstKind::Unevaluated(uneval) = c.kind() {
23422342
// Avoid the round-trip via valtree, evaluate directly to ConstValue.
2343-
uv.expand()
2343+
let (param_env, uneval) = uneval.prepare_for_eval(tcx, param_env);
2344+
(uneval.expand(), param_env)
23442345
} else {
23452346
// It's already a valtree, or an error.
23462347
let val = c.eval(tcx, param_env, span)?;
23472348
return Ok(tcx.valtree_to_const_val((self.ty(), val)));
23482349
}
23492350
}
2350-
ConstantKind::Unevaluated(uneval, _) => uneval,
2351+
ConstantKind::Unevaluated(uneval, _) => (uneval, param_env),
23512352
ConstantKind::Val(val, _) => return Ok(val),
23522353
};
23532354
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`

compiler/rustc_middle/src/ty/consts.rs

+2-24
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ impl<'tcx> Const<'tcx> {
276276
}
277277

278278
/// Returns the evaluated constant
279+
#[inline]
279280
pub fn eval(
280281
self,
281282
tcx: TyCtxt<'tcx>,
@@ -285,32 +286,9 @@ impl<'tcx> Const<'tcx> {
285286
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
286287
match self.kind() {
287288
ConstKind::Unevaluated(unevaluated) => {
288-
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
289-
// also does later, but we want to do it before checking for
290-
// inference variables.
291-
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
292-
// so that we don't try to invoke this query with
293-
// any region variables.
294-
295-
// HACK(eddyb) when the query key would contain inference variables,
296-
// attempt using identity args and `ParamEnv` instead, that will succeed
297-
// when the expression doesn't depend on any parameters.
298-
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
299-
// we can call `infcx.const_eval_resolve` which handles inference variables.
300-
let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
301-
tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
302-
def: unevaluated.def,
303-
args: GenericArgs::identity_for_item(tcx, unevaluated.def),
304-
})
305-
} else {
306-
tcx.erase_regions(param_env)
307-
.with_reveal_all_normalized(tcx)
308-
.and(tcx.erase_regions(unevaluated))
309-
};
310-
311289
// FIXME(eddyb) maybe the `const_eval_*` methods should take
312290
// `ty::ParamEnvAnd` instead of having them separate.
313-
let (param_env, unevaluated) = param_env_and.into_parts();
291+
let (param_env, unevaluated) = unevaluated.prepare_for_eval(tcx, param_env);
314292
// try to resolve e.g. associated constants to their definition on an impl, and then
315293
// evaluate the const.
316294
let c = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)?;

compiler/rustc_middle/src/ty/consts/kind.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::Const;
22
use crate::mir;
33
use crate::ty::abstract_const::CastKind;
44
use crate::ty::GenericArgsRef;
5-
use crate::ty::{self, List, Ty};
5+
use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt};
66
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
77
use rustc_hir::def_id::DefId;
88
use rustc_macros::HashStable;
@@ -26,6 +26,39 @@ impl<'tcx> UnevaluatedConst<'tcx> {
2626
pub fn expand(self) -> mir::UnevaluatedConst<'tcx> {
2727
mir::UnevaluatedConst { def: self.def, args: self.args, promoted: None }
2828
}
29+
30+
/// FIXME(RalfJung): I cannot explain what this does or why it makes sense, but not doing this
31+
/// hurts performance.
32+
#[inline]
33+
pub(crate) fn prepare_for_eval(
34+
self,
35+
tcx: TyCtxt<'tcx>,
36+
param_env: ty::ParamEnv<'tcx>,
37+
) -> (ty::ParamEnv<'tcx>, Self) {
38+
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
39+
// also does later, but we want to do it before checking for
40+
// inference variables.
41+
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
42+
// so that we don't try to invoke this query with
43+
// any region variables.
44+
45+
// HACK(eddyb) when the query key would contain inference variables,
46+
// attempt using identity args and `ParamEnv` instead, that will succeed
47+
// when the expression doesn't depend on any parameters.
48+
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
49+
// we can call `infcx.const_eval_resolve` which handles inference variables.
50+
if (param_env, self).has_non_region_infer() {
51+
(
52+
tcx.param_env(self.def),
53+
ty::UnevaluatedConst {
54+
def: self.def,
55+
args: ty::GenericArgs::identity_for_item(tcx, self.def),
56+
},
57+
)
58+
} else {
59+
(tcx.erase_regions(param_env).with_reveal_all_normalized(tcx), tcx.erase_regions(self))
60+
}
61+
}
2962
}
3063

3164
impl<'tcx> UnevaluatedConst<'tcx> {

0 commit comments

Comments
 (0)