Skip to content

Commit 7a90e84

Browse files
committed
InterpCx store TypingEnv instead of a ParamEnv
1 parent b9dea31 commit 7a90e84

File tree

36 files changed

+167
-192
lines changed

36 files changed

+167
-192
lines changed

Diff for: compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,11 @@ fn codegen_regular_intrinsic_call<'tcx>(
744744

745745
let const_val = fx
746746
.tcx
747-
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, source_info.span)
747+
.const_eval_instance(
748+
ty::TypingEnv::fully_monomorphized(),
749+
instance,
750+
source_info.span,
751+
)
748752
.unwrap();
749753
let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty);
750754
ret.write_cvalue(fx, val);

Diff for: compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
146146
| sym::type_id
147147
| sym::type_name
148148
| sym::variant_count => {
149-
let value = bx
150-
.tcx()
151-
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, span)
152-
.unwrap();
149+
let value = bx.tcx().const_eval_instance(bx.typing_env(), instance, span).unwrap();
153150
OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
154151
}
155152
sym::arith_offset => {

Diff for: compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+20-30
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use rustc_middle::bug;
77
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
88
use rustc_middle::mir::{self, ConstAlloc, ConstValue};
99
use rustc_middle::query::TyCtxtAt;
10-
use rustc_middle::traits::Reveal;
1110
use rustc_middle::ty::layout::LayoutOf;
1211
use rustc_middle::ty::print::with_no_trimmed_paths;
1312
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -31,7 +30,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
3130
cid: GlobalId<'tcx>,
3231
body: &'tcx mir::Body<'tcx>,
3332
) -> InterpResult<'tcx, R> {
34-
trace!(?ecx.param_env);
33+
trace!(?ecx.typing_env);
3534
let tcx = *ecx.tcx;
3635
assert!(
3736
cid.promoted.is_some()
@@ -126,14 +125,14 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
126125
pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
127126
tcx: TyCtxt<'tcx>,
128127
root_span: Span,
129-
param_env: ty::ParamEnv<'tcx>,
128+
typing_env: ty::TypingEnv<'tcx>,
130129
can_access_mut_global: CanAccessMutGlobal,
131130
) -> CompileTimeInterpCx<'tcx> {
132-
debug!("mk_eval_cx: {:?}", param_env);
131+
debug!("mk_eval_cx: {:?}", typing_env);
133132
InterpCx::new(
134133
tcx,
135134
root_span,
136-
param_env,
135+
typing_env,
137136
CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No),
138137
)
139138
}
@@ -142,11 +141,11 @@ pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
142141
/// Returns both the context and an `OpTy` that represents the constant.
143142
pub fn mk_eval_cx_for_const_val<'tcx>(
144143
tcx: TyCtxtAt<'tcx>,
145-
param_env: ty::ParamEnv<'tcx>,
144+
typing_env: ty::TypingEnv<'tcx>,
146145
val: mir::ConstValue<'tcx>,
147146
ty: Ty<'tcx>,
148147
) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> {
149-
let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No);
148+
let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, typing_env, CanAccessMutGlobal::No);
150149
// FIXME: is it a problem to discard the error here?
151150
let op = ecx.const_val_to_op(val, ty, None).discard_err()?;
152151
Some((ecx, op))
@@ -221,7 +220,7 @@ pub(super) fn op_to_const<'tcx>(
221220
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
222221
debug_assert!(
223222
matches!(
224-
ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(),
223+
ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env).kind(),
225224
ty::Str | ty::Slice(..),
226225
),
227226
"`ConstValue::Slice` is for slice-tailed types only, but got {}",
@@ -245,7 +244,7 @@ pub(super) fn op_to_const<'tcx>(
245244
pub(crate) fn turn_into_const_value<'tcx>(
246245
tcx: TyCtxt<'tcx>,
247246
constant: ConstAlloc<'tcx>,
248-
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
247+
key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
249248
) -> ConstValue<'tcx> {
250249
let cid = key.value;
251250
let def_id = cid.instance.def.def_id();
@@ -254,7 +253,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
254253
let ecx = mk_eval_cx_to_read_const_val(
255254
tcx,
256255
tcx.def_span(key.value.instance.def_id()),
257-
key.param_env,
256+
key.typing_env,
258257
CanAccessMutGlobal::from(is_static),
259258
);
260259

@@ -274,23 +273,16 @@ pub(crate) fn turn_into_const_value<'tcx>(
274273
#[instrument(skip(tcx), level = "debug")]
275274
pub fn eval_to_const_value_raw_provider<'tcx>(
276275
tcx: TyCtxt<'tcx>,
277-
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
276+
key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
278277
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
279-
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
280-
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
281-
// types that are not specified in the opaque type.
282-
assert_eq!(key.param_env.reveal(), Reveal::All);
283-
let typing_env =
284-
ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: key.param_env };
285-
286278
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
287279
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
288280
if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def {
289-
let ty = key.value.instance.ty(tcx, typing_env);
281+
let ty = key.value.instance.ty(tcx, key.typing_env);
290282
let ty::FnDef(_, args) = ty.kind() else {
291283
bug!("intrinsic with type {:?}", ty);
292284
};
293-
return eval_nullary_intrinsic(tcx, key.param_env, def_id, args).report_err().map_err(
285+
return eval_nullary_intrinsic(tcx, key.typing_env, def_id, args).report_err().map_err(
294286
|error| {
295287
let span = tcx.def_span(def_id);
296288

@@ -317,7 +309,7 @@ pub fn eval_static_initializer_provider<'tcx>(
317309

318310
let instance = ty::Instance::mono(tcx, def_id.to_def_id());
319311
let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None };
320-
eval_in_interpreter(tcx, cid, ty::ParamEnv::reveal_all())
312+
eval_in_interpreter(tcx, cid, ty::TypingEnv::fully_monomorphized())
321313
}
322314

323315
pub trait InterpretationResult<'tcx> {
@@ -342,16 +334,14 @@ impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
342334
#[instrument(skip(tcx), level = "debug")]
343335
pub fn eval_to_allocation_raw_provider<'tcx>(
344336
tcx: TyCtxt<'tcx>,
345-
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
337+
key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
346338
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
347339
// This shouldn't be used for statics, since statics are conceptually places,
348340
// not values -- so what we do here could break pointer identity.
349341
assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id()));
350-
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
351-
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
352-
// types that are not specified in the opaque type.
353-
354-
assert_eq!(key.param_env.reveal(), Reveal::All);
342+
// Const eval always happens in PostAnalysis mode . See the comment in
343+
// `InterpCx::new` for more details.
344+
debug_assert_eq!(key.typing_env.typing_mode, ty::TypingMode::PostAnalysis);
355345
if cfg!(debug_assertions) {
356346
// Make sure we format the instance even if we do not print it.
357347
// This serves as a regression test against an ICE on printing.
@@ -362,21 +352,21 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
362352
trace!("const eval: {:?} ({})", key, instance);
363353
}
364354

365-
eval_in_interpreter(tcx, key.value, key.param_env)
355+
eval_in_interpreter(tcx, key.value, key.typing_env)
366356
}
367357

368358
fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
369359
tcx: TyCtxt<'tcx>,
370360
cid: GlobalId<'tcx>,
371-
param_env: ty::ParamEnv<'tcx>,
361+
typing_env: ty::TypingEnv<'tcx>,
372362
) -> Result<R, ErrorHandled> {
373363
let def = cid.instance.def.def_id();
374364
let is_static = tcx.is_static(def);
375365

376366
let mut ecx = InterpCx::new(
377367
tcx,
378368
tcx.def_span(def),
379-
param_env,
369+
typing_env,
380370
// Statics (and promoteds inside statics) may access mutable global memory, because unlike consts
381371
// they do not have to behave "as if" they were evaluated at runtime.
382372
// For consts however we want to ensure they behave "as if" they were evaluated at runtime,

Diff for: compiler/rustc_const_eval/src/const_eval/machine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
667667
.is_some_and(|p| !p.immutable())
668668
{
669669
// That next check is expensive, that's why we have all the guards above.
670-
let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env());
670+
let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env);
671671
let place = ecx.ref_to_mplace(val)?;
672672
let new_place = if is_immutable {
673673
place.map_provenance(CtfeProvenance::as_immutable)

Diff for: compiler/rustc_const_eval/src/const_eval/mod.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
3838
val: mir::ConstValue<'tcx>,
3939
ty: Ty<'tcx>,
4040
) -> Option<mir::DestructuredConstant<'tcx>> {
41-
let param_env = ty::ParamEnv::reveal_all();
42-
let (ecx, op) = mk_eval_cx_for_const_val(tcx, param_env, val, ty)?;
41+
let typing_env = ty::TypingEnv::fully_monomorphized();
42+
let (ecx, op) = mk_eval_cx_for_const_val(tcx, typing_env, val, ty)?;
4343

4444
// We go to `usize` as we cannot allocate anything bigger anyway.
4545
let (field_count, variant, down) = match ty.kind() {
@@ -76,10 +76,12 @@ pub fn tag_for_variant_provider<'tcx>(
7676
) -> Option<ty::ScalarInt> {
7777
assert!(ty.is_enum());
7878

79+
// FIXME: This uses an empty `TypingEnv` even though
80+
// it may be used by a generic CTFE.
7981
let ecx = InterpCx::new(
8082
tcx,
8183
ty.default_span(tcx),
82-
ty::ParamEnv::reveal_all(),
84+
ty::TypingEnv::fully_monomorphized(),
8385
crate::const_eval::DummyMachine,
8486
);
8587

Diff for: compiler/rustc_const_eval/src/const_eval/valtrees.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ 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;
65
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
76
use rustc_middle::{bug, mir};
87
use rustc_span::DUMMY_SP;
@@ -229,16 +228,19 @@ fn create_valtree_place<'tcx>(
229228
/// Evaluates a constant and turns it into a type-level constant value.
230229
pub(crate) fn eval_to_valtree<'tcx>(
231230
tcx: TyCtxt<'tcx>,
232-
param_env: ty::ParamEnv<'tcx>,
231+
typing_env: ty::TypingEnv<'tcx>,
233232
cid: GlobalId<'tcx>,
234233
) -> EvalToValTreeResult<'tcx> {
235-
let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?;
234+
// Const eval always happens in PostAnalysis mode . See the comment in
235+
// `InterpCx::new` for more details.
236+
debug_assert_eq!(typing_env.typing_mode, ty::TypingMode::PostAnalysis);
237+
let const_alloc = tcx.eval_to_allocation_raw(typing_env.as_query_input(cid))?;
236238

237239
// FIXME Need to provide a span to `eval_to_valtree`
238240
let ecx = mk_eval_cx_to_read_const_val(
239241
tcx,
240242
DUMMY_SP,
241-
param_env,
243+
typing_env,
242244
// It is absolutely crucial for soundness that
243245
// we do not read from mutable memory.
244246
CanAccessMutGlobal::No,
@@ -273,7 +275,8 @@ pub(crate) fn eval_to_valtree<'tcx>(
273275
#[instrument(skip(tcx), level = "debug", ret)]
274276
pub fn valtree_to_const_value<'tcx>(
275277
tcx: TyCtxt<'tcx>,
276-
param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
278+
typing_env: ty::TypingEnv<'tcx>,
279+
ty: Ty<'tcx>,
277280
valtree: ty::ValTree<'tcx>,
278281
) -> mir::ConstValue<'tcx> {
279282
// Basic idea: We directly construct `Scalar` values from trivial `ValTree`s
@@ -282,10 +285,6 @@ pub fn valtree_to_const_value<'tcx>(
282285
// the `ValTree` and using `place_projection` and `place_field` to
283286
// create inner `MPlace`s which are filled recursively.
284287
// FIXME Does this need an example?
285-
let (param_env, ty) = param_env_ty.into_parts();
286-
debug_assert_eq!(param_env.reveal(), Reveal::All);
287-
let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env };
288-
289288
match *ty.kind() {
290289
ty::FnDef(..) => {
291290
assert!(valtree.unwrap_branch().is_empty());
@@ -299,10 +298,10 @@ pub fn valtree_to_const_value<'tcx>(
299298
),
300299
}
301300
}
302-
ty::Pat(ty, _) => valtree_to_const_value(tcx, param_env.and(ty), valtree),
301+
ty::Pat(ty, _) => valtree_to_const_value(tcx, typing_env, ty, valtree),
303302
ty::Ref(_, inner_ty, _) => {
304303
let mut ecx =
305-
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
304+
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No);
306305
let imm = valtree_to_ref(&mut ecx, valtree, inner_ty);
307306
let imm =
308307
ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap());
@@ -324,14 +323,14 @@ pub fn valtree_to_const_value<'tcx>(
324323
for (i, &inner_valtree) in branches.iter().enumerate() {
325324
let field = layout.field(&LayoutCx::new(tcx, typing_env), i);
326325
if !field.is_zst() {
327-
return valtree_to_const_value(tcx, param_env.and(field.ty), inner_valtree);
326+
return valtree_to_const_value(tcx, typing_env, field.ty, inner_valtree);
328327
}
329328
}
330329
bug!("could not find non-ZST field during in {layout:#?}");
331330
}
332331

333332
let mut ecx =
334-
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
333+
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No);
335334

336335
// Need to create a place for this valtree.
337336
let place = create_valtree_place(&mut ecx, layout, valtree);

Diff for: compiler/rustc_const_eval/src/interpret/call.rs

+29-29
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
215215
// Even if `ty` is normalized, the search for the unsized tail will project
216216
// to fields, which can yield non-normalized types. So we need to provide a
217217
// normalization function.
218-
let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env(), ty);
218+
let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env, ty);
219219
ty.ptr_metadata_ty(*self.tcx, normalize)
220220
};
221221
return interp_ok(meta_ty(caller) == meta_ty(callee));
@@ -652,35 +652,35 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
652652
};
653653

654654
// Obtain the underlying trait we are working on, and the adjusted receiver argument.
655-
let (trait_, dyn_ty, adjusted_recv) =
656-
if let ty::Dynamic(data, _, ty::DynStar) = receiver_place.layout.ty.kind() {
657-
let recv = self.unpack_dyn_star(&receiver_place, data)?;
655+
let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) =
656+
receiver_place.layout.ty.kind()
657+
{
658+
let recv = self.unpack_dyn_star(&receiver_place, data)?;
658659

659-
(data.principal(), recv.layout.ty, recv.ptr())
660-
} else {
661-
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
662-
// (For that reason we also cannot use `unpack_dyn_trait`.)
663-
let receiver_tail = self
664-
.tcx
665-
.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env());
666-
let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
667-
span_bug!(
668-
self.cur_span(),
669-
"dynamic call on non-`dyn` type {}",
670-
receiver_tail
671-
)
672-
};
673-
assert!(receiver_place.layout.is_unsized());
674-
675-
// Get the required information from the vtable.
676-
let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
677-
let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
678-
679-
// It might be surprising that we use a pointer as the receiver even if this
680-
// is a by-val case; this works because by-val passing of an unsized `dyn
681-
// Trait` to a function is actually desugared to a pointer.
682-
(receiver_trait.principal(), dyn_ty, receiver_place.ptr())
660+
(data.principal(), recv.layout.ty, recv.ptr())
661+
} else {
662+
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
663+
// (For that reason we also cannot use `unpack_dyn_trait`.)
664+
let receiver_tail =
665+
self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env);
666+
let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
667+
span_bug!(
668+
self.cur_span(),
669+
"dynamic call on non-`dyn` type {}",
670+
receiver_tail
671+
)
683672
};
673+
assert!(receiver_place.layout.is_unsized());
674+
675+
// Get the required information from the vtable.
676+
let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
677+
let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
678+
679+
// It might be surprising that we use a pointer as the receiver even if this
680+
// is a by-val case; this works because by-val passing of an unsized `dyn
681+
// Trait` to a function is actually desugared to a pointer.
682+
(receiver_trait.principal(), dyn_ty, receiver_place.ptr())
683+
};
684684

685685
// Now determine the actual method to call. Usually we use the easy way of just
686686
// looking up the method at index `idx`.
@@ -704,7 +704,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
704704

705705
let concrete_method = Instance::expect_resolve_for_vtable(
706706
tcx,
707-
self.typing_env(),
707+
self.typing_env,
708708
def_id,
709709
instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
710710
self.cur_span(),

Diff for: compiler/rustc_const_eval/src/interpret/cast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
8383
ty::FnDef(def_id, args) => {
8484
let instance = ty::Instance::resolve_for_fn_ptr(
8585
*self.tcx,
86-
self.typing_env(),
86+
self.typing_env,
8787
def_id,
8888
args,
8989
)
@@ -384,7 +384,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
384384
) -> InterpResult<'tcx> {
385385
// A<Struct> -> A<Trait> conversion
386386
let (src_pointee_ty, dest_pointee_ty) =
387-
self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env());
387+
self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env);
388388

389389
match (src_pointee_ty.kind(), dest_pointee_ty.kind()) {
390390
(&ty::Array(_, length), &ty::Slice(_)) => {

0 commit comments

Comments
 (0)