Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

continue ParamEnv to TypingEnv transition #133212

Merged
merged 12 commits into from
Nov 20, 2024
3 changes: 2 additions & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1727,7 +1727,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `Sized` bound in no way depends on precise regions, so this
// shouldn't affect `is_sized`.
let erased_ty = tcx.erase_regions(ty);
if !erased_ty.is_sized(tcx, self.infcx.param_env) {
// FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here.
if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
// in current MIR construction, all non-control-flow rvalue
// expressions evaluate through `as_temp` or `into` a return
// slot or local, so to find all unsized rvalues it is enough
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::InlineAsmMacro;
use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv};
use rustc_middle::ty::print::with_no_trimmed_paths;

use crate::constant::ConstantCx;
Expand Down Expand Up @@ -841,7 +841,7 @@ fn codegen_stmt<'tcx>(
lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
}
Rvalue::NullaryOp(ref null_op, ty) => {
assert!(lval.layout().ty.is_sized(fx.tcx, ty::ParamEnv::reveal_all()));
assert!(lval.layout().ty.is_sized(fx.tcx, fx.typing_env()));
let layout = fx.layout_of(fx.monomorphize(ty));
let val = match null_op {
NullOp::SizeOf => layout.size.bytes(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ fn clif_pair_type_from_ty<'tcx>(

/// Is a pointer to this type a wide ptr?
pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
if ty.is_sized(tcx, ty::ParamEnv::reveal_all()) {
if ty.is_sized(tcx, ty::TypingEnv::fully_monomorphized()) {
return false;
}

Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,11 @@ fn codegen_regular_intrinsic_call<'tcx>(

let const_val = fx
.tcx
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, source_info.span)
.const_eval_instance(
ty::TypingEnv::fully_monomorphized(),
instance,
source_info.span,
)
.unwrap();
let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty);
ret.write_cvalue(fx, val);
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use rustc_middle::mir::BinOp;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_session::Session;
use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
use rustc_span::symbol::sym;
Expand Down Expand Up @@ -119,7 +119,8 @@ pub fn validate_trivial_unsize<'tcx>(
) -> bool {
match (source_data.principal(), target_data.principal()) {
(Some(hr_source_principal), Some(hr_target_principal)) => {
let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
let (infcx, param_env) =
tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized());
let universe = infcx.universe();
let ocx = ObligationCtxt::new(&infcx);
infcx.enter_forall(hr_target_principal, |target_principal| {
Expand All @@ -130,7 +131,7 @@ pub fn validate_trivial_unsize<'tcx>(
);
let Ok(()) = ocx.eq_trace(
&ObligationCause::dummy(),
ty::ParamEnv::reveal_all(),
param_env,
ToTrace::to_trace(
&ObligationCause::dummy(),
hr_target_principal,
Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
| sym::type_id
| sym::type_name
| sym::variant_count => {
let value = bx
.tcx()
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, span)
.unwrap();
let value = bx.tcx().const_eval_instance(bx.typing_env(), instance, span).unwrap();
OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
}
sym::arith_offset => {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_ssa/src/traits/type_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,15 @@ pub trait DerivedTypeCodegenMethods<'tcx>:
}

fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
ty.is_sized(self.tcx(), ty::ParamEnv::reveal_all())
ty.is_sized(self.tcx(), self.typing_env())
}

fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all())
ty.is_freeze(self.tcx(), self.typing_env())
}

fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
if ty.is_sized(self.tcx(), self.param_env()) {
if ty.is_sized(self.tcx(), self.typing_env()) {
return false;
}

Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_const_eval/src/check_consts/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,7 @@ where
///
/// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool {
!place
.ty(self.ccx.body, self.ccx.tcx)
.ty
.is_freeze(self.ccx.tcx, self.ccx.typing_env.param_env)
!place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.typing_env)
}
}

Expand Down
50 changes: 20 additions & 30 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use rustc_middle::bug;
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
use rustc_middle::mir::{self, ConstAlloc, ConstValue};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::traits::Reveal;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TyCtxt};
Expand All @@ -31,7 +30,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
cid: GlobalId<'tcx>,
body: &'tcx mir::Body<'tcx>,
) -> InterpResult<'tcx, R> {
trace!(?ecx.param_env);
trace!(?ecx.typing_env);
let tcx = *ecx.tcx;
assert!(
cid.promoted.is_some()
Expand Down Expand Up @@ -126,14 +125,14 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
tcx: TyCtxt<'tcx>,
root_span: Span,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
can_access_mut_global: CanAccessMutGlobal,
) -> CompileTimeInterpCx<'tcx> {
debug!("mk_eval_cx: {:?}", param_env);
debug!("mk_eval_cx: {:?}", typing_env);
InterpCx::new(
tcx,
root_span,
param_env,
typing_env,
CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No),
)
}
Expand All @@ -142,11 +141,11 @@ pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
/// Returns both the context and an `OpTy` that represents the constant.
pub fn mk_eval_cx_for_const_val<'tcx>(
tcx: TyCtxtAt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
val: mir::ConstValue<'tcx>,
ty: Ty<'tcx>,
) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> {
let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No);
let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, typing_env, CanAccessMutGlobal::No);
// FIXME: is it a problem to discard the error here?
let op = ecx.const_val_to_op(val, ty, None).discard_err()?;
Some((ecx, op))
Expand Down Expand Up @@ -221,7 +220,7 @@ pub(super) fn op_to_const<'tcx>(
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
debug_assert!(
matches!(
ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(),
ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env).kind(),
ty::Str | ty::Slice(..),
),
"`ConstValue::Slice` is for slice-tailed types only, but got {}",
Expand All @@ -245,7 +244,7 @@ pub(super) fn op_to_const<'tcx>(
pub(crate) fn turn_into_const_value<'tcx>(
tcx: TyCtxt<'tcx>,
constant: ConstAlloc<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
) -> ConstValue<'tcx> {
let cid = key.value;
let def_id = cid.instance.def.def_id();
Expand All @@ -254,7 +253,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
let ecx = mk_eval_cx_to_read_const_val(
tcx,
tcx.def_span(key.value.instance.def_id()),
key.param_env,
key.typing_env,
CanAccessMutGlobal::from(is_static),
);

Expand All @@ -274,23 +273,16 @@ pub(crate) fn turn_into_const_value<'tcx>(
#[instrument(skip(tcx), level = "debug")]
pub fn eval_to_const_value_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
// types that are not specified in the opaque type.
assert_eq!(key.param_env.reveal(), Reveal::All);
let typing_env =
ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: key.param_env };

// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def {
let ty = key.value.instance.ty(tcx, typing_env);
let ty = key.value.instance.ty(tcx, key.typing_env);
let ty::FnDef(_, args) = ty.kind() else {
bug!("intrinsic with type {:?}", ty);
};
return eval_nullary_intrinsic(tcx, key.param_env, def_id, args).report_err().map_err(
return eval_nullary_intrinsic(tcx, key.typing_env, def_id, args).report_err().map_err(
|error| {
let span = tcx.def_span(def_id);

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

let instance = ty::Instance::mono(tcx, def_id.to_def_id());
let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None };
eval_in_interpreter(tcx, cid, ty::ParamEnv::reveal_all())
eval_in_interpreter(tcx, cid, ty::TypingEnv::fully_monomorphized())
}

pub trait InterpretationResult<'tcx> {
Expand All @@ -342,16 +334,14 @@ impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
#[instrument(skip(tcx), level = "debug")]
pub fn eval_to_allocation_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
// This shouldn't be used for statics, since statics are conceptually places,
// not values -- so what we do here could break pointer identity.
assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id()));
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
// types that are not specified in the opaque type.

assert_eq!(key.param_env.reveal(), Reveal::All);
// Const eval always happens in PostAnalysis mode . See the comment in
// `InterpCx::new` for more details.
debug_assert_eq!(key.typing_env.typing_mode, ty::TypingMode::PostAnalysis);
if cfg!(debug_assertions) {
// Make sure we format the instance even if we do not print it.
// This serves as a regression test against an ICE on printing.
Expand All @@ -362,21 +352,21 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
trace!("const eval: {:?} ({})", key, instance);
}

eval_in_interpreter(tcx, key.value, key.param_env)
eval_in_interpreter(tcx, key.value, key.typing_env)
}

fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
tcx: TyCtxt<'tcx>,
cid: GlobalId<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
) -> Result<R, ErrorHandled> {
let def = cid.instance.def.def_id();
let is_static = tcx.is_static(def);

let mut ecx = InterpCx::new(
tcx,
tcx.def_span(def),
param_env,
typing_env,
// Statics (and promoteds inside statics) may access mutable global memory, because unlike consts
// they do not have to behave "as if" they were evaluated at runtime.
// For consts however we want to ensure they behave "as if" they were evaluated at runtime,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
.is_some_and(|p| !p.immutable())
{
// That next check is expensive, that's why we have all the guards above.
let is_immutable = ty.is_freeze(*ecx.tcx, ecx.param_env);
let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env);
let place = ecx.ref_to_mplace(val)?;
let new_place = if is_immutable {
place.map_provenance(CtfeProvenance::as_immutable)
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_const_eval/src/const_eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
val: mir::ConstValue<'tcx>,
ty: Ty<'tcx>,
) -> Option<mir::DestructuredConstant<'tcx>> {
let param_env = ty::ParamEnv::reveal_all();
let (ecx, op) = mk_eval_cx_for_const_val(tcx, param_env, val, ty)?;
let typing_env = ty::TypingEnv::fully_monomorphized();
let (ecx, op) = mk_eval_cx_for_const_val(tcx, typing_env, val, ty)?;

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

// FIXME: This uses an empty `TypingEnv` even though
// it may be used by a generic CTFE.
let ecx = InterpCx::new(
tcx,
ty.default_span(tcx),
ty::ParamEnv::reveal_all(),
ty::TypingEnv::fully_monomorphized(),
crate::const_eval::DummyMachine,
);

Expand Down
25 changes: 12 additions & 13 deletions compiler/rustc_const_eval/src/const_eval/valtrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use rustc_abi::{BackendRepr, VariantIdx};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
use rustc_middle::ty::solve::Reveal;
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
use rustc_middle::{bug, mir};
use rustc_span::DUMMY_SP;
Expand Down Expand Up @@ -229,16 +228,19 @@ fn create_valtree_place<'tcx>(
/// Evaluates a constant and turns it into a type-level constant value.
pub(crate) fn eval_to_valtree<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
cid: GlobalId<'tcx>,
) -> EvalToValTreeResult<'tcx> {
let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?;
// Const eval always happens in PostAnalysis mode . See the comment in
// `InterpCx::new` for more details.
debug_assert_eq!(typing_env.typing_mode, ty::TypingMode::PostAnalysis);
let const_alloc = tcx.eval_to_allocation_raw(typing_env.as_query_input(cid))?;

// FIXME Need to provide a span to `eval_to_valtree`
let ecx = mk_eval_cx_to_read_const_val(
tcx,
DUMMY_SP,
param_env,
typing_env,
// It is absolutely crucial for soundness that
// we do not read from mutable memory.
CanAccessMutGlobal::No,
Expand Down Expand Up @@ -273,7 +275,8 @@ pub(crate) fn eval_to_valtree<'tcx>(
#[instrument(skip(tcx), level = "debug", ret)]
pub fn valtree_to_const_value<'tcx>(
tcx: TyCtxt<'tcx>,
param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
valtree: ty::ValTree<'tcx>,
) -> mir::ConstValue<'tcx> {
// Basic idea: We directly construct `Scalar` values from trivial `ValTree`s
Expand All @@ -282,10 +285,6 @@ pub fn valtree_to_const_value<'tcx>(
// the `ValTree` and using `place_projection` and `place_field` to
// create inner `MPlace`s which are filled recursively.
// FIXME Does this need an example?
let (param_env, ty) = param_env_ty.into_parts();
debug_assert_eq!(param_env.reveal(), Reveal::All);
let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env };

match *ty.kind() {
ty::FnDef(..) => {
assert!(valtree.unwrap_branch().is_empty());
Expand All @@ -299,10 +298,10 @@ pub fn valtree_to_const_value<'tcx>(
),
}
}
ty::Pat(ty, _) => valtree_to_const_value(tcx, param_env.and(ty), valtree),
ty::Pat(ty, _) => valtree_to_const_value(tcx, typing_env, ty, valtree),
ty::Ref(_, inner_ty, _) => {
let mut ecx =
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No);
let imm = valtree_to_ref(&mut ecx, valtree, inner_ty);
let imm =
ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap());
Expand All @@ -324,14 +323,14 @@ pub fn valtree_to_const_value<'tcx>(
for (i, &inner_valtree) in branches.iter().enumerate() {
let field = layout.field(&LayoutCx::new(tcx, typing_env), i);
if !field.is_zst() {
return valtree_to_const_value(tcx, param_env.and(field.ty), inner_valtree);
return valtree_to_const_value(tcx, typing_env, field.ty, inner_valtree);
}
}
bug!("could not find non-ZST field during in {layout:#?}");
}

let mut ecx =
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No);

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