Skip to content

Commit 8b79e04

Browse files
committed
Auto merge of rust-lang#132418 - lcnr:prepare-for-eval, r=<try>
do not eagerly use `Reveal::All` in `const_eval_resolve_for_typeck` We should not use `RevealAll` when resolving the instance; only when evaluating its body. r? `@BoxyUwU`
2 parents 20c909f + 780bd2f commit 8b79e04

File tree

6 files changed

+18
-54
lines changed

6 files changed

+18
-54
lines changed

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

-1
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,6 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
348348
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
349349
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
350350
// types that are not specified in the opaque type.
351-
352351
assert_eq!(key.param_env.reveal(), Reveal::All);
353352
if cfg!(debug_assertions) {
354353
// Make sure we format the instance even if we do not print it.

compiler/rustc_const_eval/src/const_eval/valtrees.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use rustc_abi::{BackendRepr, VariantIdx};
22
use rustc_data_structures::stack::ensure_sufficient_stack;
33
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
44
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
5+
use rustc_middle::ty::solve::Reveal;
56
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
67
use rustc_middle::{bug, mir};
78
use rustc_span::DUMMY_SP;
@@ -231,6 +232,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
231232
param_env: ty::ParamEnv<'tcx>,
232233
cid: GlobalId<'tcx>,
233234
) -> EvalToValTreeResult<'tcx> {
235+
debug_assert_eq!(param_env.reveal(), Reveal::All);
234236
let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?;
235237

236238
// FIXME Need to provide a span to `eval_to_valtree`

compiler/rustc_infer/src/infer/mod.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -1345,16 +1345,10 @@ impl<'tcx> InferCtxt<'tcx> {
13451345
}
13461346
}
13471347

1348-
let param_env_erased = tcx.erase_regions(param_env);
1349-
let args_erased = tcx.erase_regions(args);
1350-
debug!(?param_env_erased);
1351-
debug!(?args_erased);
1352-
1353-
let unevaluated = ty::UnevaluatedConst { def: unevaluated.def, args: args_erased };
1354-
1348+
let unevaluated = ty::UnevaluatedConst { def: unevaluated.def, args };
13551349
// The return value is the evaluated value which doesn't contain any reference to inference
13561350
// variables, thus we don't need to instantiate back the original values.
1357-
tcx.const_eval_resolve_for_typeck(param_env_erased, unevaluated, span)
1351+
tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)
13581352
}
13591353

13601354
/// The returned function is used in a fast path. If it returns `true` the variable is

compiler/rustc_middle/src/mir/interpret/queries.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl<'tcx> TyCtxt<'tcx> {
4141
let args = GenericArgs::identity_for_item(self, def_id);
4242
let instance = ty::Instance::new(def_id, args);
4343
let cid = GlobalId { instance, promoted: None };
44-
let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
44+
let param_env = self.param_env_reveal_all_normalized(def_id);
4545
let inputs = self.erase_regions(param_env.and(cid));
4646
self.eval_to_allocation_raw(inputs)
4747
}
@@ -72,11 +72,7 @@ impl<'tcx> TyCtxt<'tcx> {
7272
bug!("did not expect inference variables here");
7373
}
7474

75-
match ty::Instance::try_resolve(
76-
self, param_env,
77-
// FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
78-
ct.def, ct.args,
79-
) {
75+
match ty::Instance::try_resolve(self, param_env, ct.def, ct.args) {
8076
Ok(Some(instance)) => {
8177
let cid = GlobalId { instance, promoted: ct.promoted };
8278
self.const_eval_global_id(param_env, cid, span)
@@ -108,6 +104,10 @@ impl<'tcx> TyCtxt<'tcx> {
108104
match ty::Instance::try_resolve(self, param_env, ct.def, ct.args) {
109105
Ok(Some(instance)) => {
110106
let cid = GlobalId { instance, promoted: None };
107+
// We always evaluate with `Reveal::All` as evaluation should be able
108+
// to observe the hidden types of opaques. Note that we've still succeeded to
109+
// typeck the body of the constant using `Reveal::UserFacing`.
110+
let param_env = self.erase_regions(param_env).with_reveal_all_normalized(self);
111111
self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
112112
// We are emitting the lint here instead of in `is_const_evaluatable`
113113
// as we normalize obligations before checking them, and normalization

compiler/rustc_middle/src/ty/consts.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,14 @@ impl<'tcx> Const<'tcx> {
376376
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
377377
match self.kind() {
378378
ConstKind::Unevaluated(unevaluated) => {
379-
// FIXME(eddyb) maybe the `const_eval_*` methods should take
380-
// `ty::ParamEnvAnd` instead of having them separate.
381-
let (param_env, unevaluated) = unevaluated.prepare_for_eval(tcx, param_env);
382-
// try to resolve e.g. associated constants to their definition on an impl, and then
379+
// Try to resolve e.g. associated constants to their definition on an impl, and then
383380
// evaluate the const.
381+
//
382+
// In case the query key would contain unconstrained inference variables, we bail instead.
383+
if (unevaluated, param_env).has_non_region_infer() {
384+
return Err(Either::Right(ErrorHandled::TooGeneric(span)));
385+
}
386+
384387
match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span) {
385388
Ok(Ok(c)) => {
386389
Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))

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

+1-35
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,12 @@
11
use std::assert_matches::assert_matches;
22

3-
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, extension};
3+
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
44

55
use super::Const;
66
use crate::mir;
77
use crate::ty::abstract_const::CastKind;
8-
use crate::ty::visit::TypeVisitableExt as _;
98
use crate::ty::{self, Ty, TyCtxt};
109

11-
#[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)]
12-
impl<'tcx> ty::UnevaluatedConst<'tcx> {
13-
/// FIXME(RalfJung): I cannot explain what this does or why it makes sense, but not doing this
14-
/// hurts performance.
15-
#[inline]
16-
fn prepare_for_eval(
17-
self,
18-
tcx: TyCtxt<'tcx>,
19-
param_env: ty::ParamEnv<'tcx>,
20-
) -> (ty::ParamEnv<'tcx>, Self) {
21-
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
22-
// also does later, but we want to do it before checking for
23-
// inference variables.
24-
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
25-
// so that we don't try to invoke this query with
26-
// any region variables.
27-
28-
// HACK(eddyb) when the query key would contain inference variables,
29-
// attempt using identity args and `ParamEnv` instead, that will succeed
30-
// when the expression doesn't depend on any parameters.
31-
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
32-
// we can call `infcx.const_eval_resolve` which handles inference variables.
33-
if (param_env, self).has_non_region_infer() {
34-
(tcx.param_env(self.def), ty::UnevaluatedConst {
35-
def: self.def,
36-
args: ty::GenericArgs::identity_for_item(tcx, self.def),
37-
})
38-
} else {
39-
(tcx.erase_regions(param_env).with_reveal_all_normalized(tcx), tcx.erase_regions(self))
40-
}
41-
}
42-
}
43-
4410
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
4511
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
4612
pub enum ExprKind {

0 commit comments

Comments
 (0)