diff options
Diffstat (limited to 'compiler/rustc_const_eval/src')
24 files changed, 145 insertions, 154 deletions
| diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index ffe32acb316..50e8a168eeb 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -388,7 +388,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { return false; } - let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx)); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(self.body.typing_env(tcx)); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let body_id = self.body.source.def_id().expect_local(); @@ -398,11 +398,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { ty::BoundConstness::Const } }; - let const_conditions = ocx.normalize( - &ObligationCause::misc(call_span, body_id), - self.param_env, - const_conditions, - ); + let const_conditions = + ocx.normalize(&ObligationCause::misc(call_span, body_id), param_env, const_conditions); ocx.register_obligations(const_conditions.into_iter().map(|(trait_ref, span)| { Obligation::new( tcx, @@ -411,7 +408,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { body_id, ObligationCauseCode::WhereClause(callee, span), ), - self.param_env, + param_env, trait_ref.to_host_effect_clause(tcx, host_polarity), ) })); diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index ebdd55a4f70..80d3c6448aa 100644 --- a/compiler/rustc_const_eval/src/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs @@ -24,17 +24,15 @@ mod resolver; pub struct ConstCx<'mir, 'tcx> { pub body: &'mir mir::Body<'tcx>, pub tcx: TyCtxt<'tcx>, - pub param_env: ty::ParamEnv<'tcx>, + pub typing_env: ty::TypingEnv<'tcx>, pub const_kind: Option<hir::ConstContext>, } impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Self { - let def_id = body.source.def_id().expect_local(); - let param_env = tcx.param_env(def_id); - + let typing_env = body.typing_env(tcx); let const_kind = tcx.hir().body_const_context(body.source.def_id().expect_local()); - ConstCx { body, tcx, param_env, const_kind } + ConstCx { body, tcx, typing_env, const_kind } } pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> { diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index ca95e42dd2b..8ba6b89aad4 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -120,7 +120,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { #[allow(rustc::untranslatable_diagnostic)] fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> { let FnCallNonConst { callee, args, span, call_source } = *self; - let ConstCx { tcx, param_env, .. } = *ccx; + let ConstCx { tcx, typing_env, .. } = *ccx; let caller = ccx.def_id(); let diag_trait = |err, self_ty: Ty<'_>, trait_id| { @@ -146,13 +146,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { } } ty::Adt(..) => { + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); - - let infcx = tcx.infer_ctxt().build(ccx.body.typing_mode(tcx)); let mut selcx = SelectionContext::new(&infcx); let implsrc = selcx.select(&obligation); - if let Ok(Some(ImplSource::UserDefined(data))) = implsrc { // FIXME(const_trait_impl) revisit this if !tcx.is_const_trait_impl(data.impl_def_id) { @@ -166,7 +164,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { }; let call_kind = - call_kind(tcx, ccx.param_env, callee, args, span, call_source.from_hir_call(), None); + call_kind(tcx, ccx.typing_env, callee, args, span, call_source.from_hir_call(), None); debug!(?call_kind); diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs index 0173a528c22..f6eb130fbd3 100644 --- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs @@ -32,17 +32,15 @@ pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool { /// This is separate from the rest of the const checking logic because it must run after drop /// elaboration. pub fn check_live_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) { - let def_id = body.source.def_id().expect_local(); - let const_kind = tcx.hir().body_const_context(def_id); - if const_kind.is_none() { + let ccx = ConstCx::new(tcx, body); + if ccx.const_kind.is_none() { return; } - if tcx.has_attr(def_id, sym::rustc_do_not_const_check) { + if tcx.has_attr(body.source.def_id(), sym::rustc_do_not_const_check) { return; } - let ccx = ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def_id) }; if !checking_enabled(&ccx) { return; } diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 29a08579175..bc416acc58d 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -106,20 +106,24 @@ impl Qualif for HasMutInterior { // Instead we invoke an obligation context manually, and provide the opaque type inference settings // that allow the trait solver to just error out instead of cycling. let freeze_def_id = cx.tcx.require_lang_item(LangItem::Freeze, Some(cx.body.span)); - + // FIXME(#132279): Once we've got a typing mode which reveals opaque types using the HIR + // typeck results without causing query cycles, we should use this here instead of defining + // opaque types. + let typing_env = ty::TypingEnv { + typing_mode: ty::TypingMode::analysis_in_body( + cx.tcx, + cx.body.source.def_id().expect_local(), + ), + param_env: cx.typing_env.param_env, + }; + let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(typing_env); + let ocx = ObligationCtxt::new(&infcx); let obligation = Obligation::new( cx.tcx, ObligationCause::dummy_with_span(cx.body.span), - cx.param_env, + param_env, ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]), ); - - // FIXME(#132279): This should eventually use the already defined hidden types. - let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::analysis_in_body( - cx.tcx, - cx.body.source.def_id().expect_local(), - )); - let ocx = ObligationCtxt::new(&infcx); ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); !errors.is_empty() @@ -156,7 +160,7 @@ impl Qualif for NeedsDrop { } fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { - ty.needs_drop(cx.tcx, cx.param_env) + ty.needs_drop(cx.tcx, cx.typing_env) } fn in_adt_inherently<'tcx>( diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index 74eb6b37fbb..03624a2ce50 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -120,7 +120,10 @@ 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.param_env) + !place + .ty(self.ccx.body, self.ccx.tcx) + .ty + .is_freeze(self.ccx.tcx, self.ccx.typing_env.param_env) } } diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index a430d9dc797..ca3ee6773a0 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -221,7 +221,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.param_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 {}", @@ -280,11 +280,13 @@ pub fn eval_to_const_value_raw_provider<'tcx>( // 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, key.param_env); + let ty = key.value.instance.ty(tcx, typing_env); let ty::FnDef(_, args) = ty.kind() else { bug!("intrinsic with type {:?}", ty); }; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index f12320cb851..19c3195aaa4 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -249,9 +249,10 @@ impl<'tcx> CompileTimeInterpCx<'tcx> { } else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) { // For panic_fmt, call const_panic_fmt instead. let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None); + // FIXME(@lcnr): why does this use an empty env if we've got a `param_env` right here. let new_instance = ty::Instance::expect_resolve( *self.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), const_def_id, instance.args, self.cur_span(), diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index ea88b2ed22e..64bedea3b3f 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -2,6 +2,7 @@ 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; @@ -281,8 +282,9 @@ 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(..) => { @@ -302,11 +304,12 @@ pub fn valtree_to_const_value<'tcx>( let mut ecx = mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No); let imm = valtree_to_ref(&mut ecx, valtree, inner_ty); - let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap()); + let imm = + ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap()); op_to_const(&ecx, &imm.into(), /* for diagnostics */ false) } ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => { - let layout = tcx.layout_of(param_env_ty).unwrap(); + let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap(); if layout.is_zst() { // Fast path to avoid some allocations. return mir::ConstValue::ZeroSized; @@ -319,7 +322,7 @@ pub fn valtree_to_const_value<'tcx>( let branches = valtree.unwrap_branch(); // Find the non-ZST field. (There can be aligned ZST!) for (i, &inner_valtree) in branches.iter().enumerate() { - let field = layout.field(&LayoutCx::new(tcx, param_env), i); + 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); } diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index ef0902e4226..6cfe4b21907 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -215,7 +215,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Even if `ty` is normalized, the search for the unsized tail will project // to fields, which can yield non-normalized types. So we need to provide a // normalization function. - let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty); + let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env(), ty); ty.ptr_metadata_ty(*self.tcx, normalize) }; return interp_ok(meta_ty(caller) == meta_ty(callee)); @@ -652,35 +652,35 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; // Obtain the underlying trait we are working on, and the adjusted receiver argument. - let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) = - receiver_place.layout.ty.kind() - { - let recv = self.unpack_dyn_star(&receiver_place, data)?; + let (trait_, dyn_ty, adjusted_recv) = + if let ty::Dynamic(data, _, ty::DynStar) = receiver_place.layout.ty.kind() { + let recv = self.unpack_dyn_star(&receiver_place, data)?; - (data.principal(), recv.layout.ty, recv.ptr()) - } else { - // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. - // (For that reason we also cannot use `unpack_dyn_trait`.) - let receiver_tail = - self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.param_env); - let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { - span_bug!( - self.cur_span(), - "dynamic call on non-`dyn` type {}", - receiver_tail - ) + (data.principal(), recv.layout.ty, recv.ptr()) + } else { + // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. + // (For that reason we also cannot use `unpack_dyn_trait`.) + let receiver_tail = self + .tcx + .struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env()); + let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { + span_bug!( + self.cur_span(), + "dynamic call on non-`dyn` type {}", + receiver_tail + ) + }; + assert!(receiver_place.layout.is_unsized()); + + // Get the required information from the vtable. + let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; + let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?; + + // It might be surprising that we use a pointer as the receiver even if this + // is a by-val case; this works because by-val passing of an unsized `dyn + // Trait` to a function is actually desugared to a pointer. + (receiver_trait.principal(), dyn_ty, receiver_place.ptr()) }; - assert!(receiver_place.layout.is_unsized()); - - // Get the required information from the vtable. - let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; - let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?; - - // It might be surprising that we use a pointer as the receiver even if this - // is a by-val case; this works because by-val passing of an unsized `dyn - // Trait` to a function is actually desugared to a pointer. - (receiver_trait.principal(), dyn_ty, receiver_place.ptr()) - }; // Now determine the actual method to call. Usually we use the easy way of just // looking up the method at index `idx`. @@ -704,7 +704,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let concrete_method = Instance::expect_resolve_for_vtable( tcx, - self.param_env, + self.typing_env(), def_id, instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args), self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 49559059265..2d1bb5c9551 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -83,7 +83,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty::FnDef(def_id, args) => { let instance = ty::Instance::resolve_for_fn_ptr( *self.tcx, - self.param_env, + self.typing_env(), def_id, args, ) @@ -384,7 +384,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx> { // A<Struct> -> A<Trait> conversion let (src_pointee_ty, dest_pointee_ty) = - self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env); + self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env()); match (src_pointee_ty.kind(), dest_pointee_ty.kind()) { (&ty::Array(_, length), &ty::Slice(_)) => { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index ff6d5b28b3b..70a696e3e3e 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -10,9 +10,7 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, }; -use rustc_middle::ty::{ - self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypingMode, Variance, -}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypingEnv, Variance}; use rustc_middle::{mir, span_bug}; use rustc_session::Limit; use rustc_span::Span; @@ -65,12 +63,12 @@ where } } -impl<'tcx, M> layout::HasParamEnv<'tcx> for InterpCx<'tcx, M> +impl<'tcx, M> layout::HasTypingEnv<'tcx> for InterpCx<'tcx, M> where M: Machine<'tcx>, { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env() } } @@ -116,8 +114,7 @@ impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> { /// This test should be symmetric, as it is primarily about layout compatibility. pub(super) fn mir_assign_valid_types<'tcx>( tcx: TyCtxt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, src: TyAndLayout<'tcx>, dest: TyAndLayout<'tcx>, ) -> bool { @@ -125,7 +122,7 @@ pub(super) fn mir_assign_valid_types<'tcx>( // all normal lifetimes are erased, higher-ranked types with their // late-bound lifetimes are still around and can lead to type // differences. - if util::relate_types(tcx, typing_mode, param_env, Variance::Covariant, src.ty, dest.ty) { + if util::relate_types(tcx, typing_env, Variance::Covariant, src.ty, dest.ty) { // Make sure the layout is equal, too -- just to be safe. Miri really // needs layout equality. For performance reason we skip this check when // the types are equal. Equal types *can* have different layouts when @@ -145,8 +142,7 @@ pub(super) fn mir_assign_valid_types<'tcx>( #[cfg_attr(not(debug_assertions), inline(always))] pub(super) fn from_known_layout<'tcx>( tcx: TyCtxtAt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, known_layout: Option<TyAndLayout<'tcx>>, compute: impl FnOnce() -> InterpResult<'tcx, TyAndLayout<'tcx>>, ) -> InterpResult<'tcx, TyAndLayout<'tcx>> { @@ -155,13 +151,7 @@ pub(super) fn from_known_layout<'tcx>( Some(known_layout) => { if cfg!(debug_assertions) { let check_layout = compute()?; - if !mir_assign_valid_types( - tcx.tcx, - typing_mode, - param_env, - check_layout, - known_layout, - ) { + if !mir_assign_valid_types(tcx.tcx, typing_env, check_layout, known_layout) { span_bug!( tcx.span, "expected type differs from actual type.\nexpected: {}\nactual: {}", @@ -211,9 +201,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } - pub fn typing_mode(&self) -> TypingMode<'tcx> { + /// During CTFE we're always in `PostAnalysis` mode. + #[inline(always)] + pub fn typing_env(&self) -> ty::TypingEnv<'tcx> { debug_assert_eq!(self.param_env.reveal(), Reveal::All); - TypingMode::PostAnalysis + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } } /// Returns the span of the currently executed statement/terminator. @@ -304,13 +296,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .instance .try_instantiate_mir_and_normalize_erasing_regions( *self.tcx, - self.param_env, + self.typing_env(), ty::EarlyBinder::bind(value), ) .map_err(|_| ErrorHandled::TooGeneric(self.cur_span())) } - /// The `args` are assumed to already be in our interpreter "universe" (param_env). + /// The `args` are assumed to already be in our interpreter "universe". pub(super) fn resolve( &self, def: DefId, @@ -319,7 +311,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { trace!("resolve: {:?}, {:#?}", def, args); trace!("param_env: {:#?}", self.param_env); trace!("args: {:#?}", args); - match ty::Instance::try_resolve(*self.tcx, self.param_env, def, args) { + match ty::Instance::try_resolve(*self.tcx, self.typing_env(), def, args) { Ok(Some(instance)) => interp_ok(instance), Ok(None) => throw_inval!(TooGeneric), @@ -328,7 +320,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } - /// Check if the two things are equal in the current param_env, using an infctx to get proper + /// Check if the two things are equal in the current param_env, using an infcx to get proper /// equality checks. #[instrument(level = "trace", skip(self), ret)] pub(super) fn eq_in_param_env<T>(&self, a: T, b: T) -> bool @@ -340,14 +332,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return true; } // Slow path: spin up an inference context to check if these traits are sufficiently equal. - let infcx = self.tcx.infer_ctxt().build(self.typing_mode()); + let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env()); let ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy_with_span(self.cur_span()); // equate the two trait refs after normalization - let a = ocx.normalize(&cause, self.param_env, a); - let b = ocx.normalize(&cause, self.param_env, b); + let a = ocx.normalize(&cause, param_env, a); + let b = ocx.normalize(&cause, param_env, b); - if let Err(terr) = ocx.eq(&cause, self.param_env, a, b) { + if let Err(terr) = ocx.eq(&cause, param_env, a, b) { trace!(?terr); return false; } @@ -572,7 +564,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let val = if self.tcx.is_static(gid.instance.def_id()) { let alloc_id = self.tcx.reserve_and_set_static_alloc(gid.instance.def_id()); - let ty = instance.ty(self.tcx.tcx, self.param_env); + let ty = instance.ty(self.tcx.tcx, self.typing_env()); mir::ConstAlloc { alloc_id, ty } } else { self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(self.param_env.and(gid)))? @@ -587,7 +579,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { layout: Option<TyAndLayout<'tcx>>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| { - let const_val = val.eval(*ecx.tcx, ecx.param_env, span).map_err(|err| { + let const_val = val.eval(*ecx.tcx, ecx.typing_env(), span).map_err(|err| { if M::ALL_CONSTS_ARE_PRECHECKED { match err { ErrorHandled::TooGeneric(..) => {}, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index d89d73824aa..fc6a1c4bbc5 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -40,6 +40,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( ) -> InterpResult<'tcx, ConstValue<'tcx>> { let tp_ty = args.type_at(0); let name = tcx.item_name(def_id); + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; interp_ok(match name { sym::type_name => { ensure_monomorphic_enough(tcx, tp_ty)?; @@ -48,11 +49,13 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( } sym::needs_drop => { ensure_monomorphic_enough(tcx, tp_ty)?; - ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)) + ConstValue::from_bool(tp_ty.needs_drop(tcx, typing_env)) } sym::pref_align_of => { // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough. - let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(*e)))?; + let layout = tcx + .layout_of(typing_env.as_query_input(tp_ty)) + .map_err(|e| err_inval!(Layout(*e)))?; ConstValue::from_target_usize(layout.align.pref.bytes(), &tcx) } sym::type_id => { @@ -355,7 +358,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let should_panic = !self .tcx - .check_validity_requirement((requirement, self.param_env.and(ty))) + .check_validity_requirement((requirement, self.typing_env().as_query_input(ty))) .map_err(|_| err_inval!(TooGeneric))?; if should_panic { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 09635c96e57..07566e9fda2 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -859,7 +859,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // # Global allocations if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) { - let (size, align) = global_alloc.size_and_align(*self.tcx, self.param_env); + let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env()); let mutbl = global_alloc.mutability(*self.tcx, self.param_env); let kind = match global_alloc { GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index a130ae89bcb..0157e6c2125 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -8,7 +8,7 @@ use rustc_abi as abi; use rustc_abi::{BackendRepr, HasDataLayout, Size}; use rustc_hir::def::Namespace; use rustc_middle::mir::interpret::ScalarSizeMismatch; -use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter}; use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, mir, span_bug, ty}; @@ -297,21 +297,25 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { #[inline] pub fn from_bool(b: bool, tcx: TyCtxt<'tcx>) -> Self { - let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(tcx.types.bool)).unwrap(); + let layout = tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tcx.types.bool)) + .unwrap(); Self::from_scalar(Scalar::from_bool(b), layout) } #[inline] pub fn from_ordering(c: std::cmp::Ordering, tcx: TyCtxt<'tcx>) -> Self { let ty = tcx.ty_ordering_enum(None); - let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap(); + let layout = + tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap(); Self::from_scalar(Scalar::from_i8(c as i8), layout) } pub fn from_pair(a: Self, b: Self, tcx: TyCtxt<'tcx>) -> Self { let layout = tcx .layout_of( - ty::ParamEnv::reveal_all().and(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])), + ty::TypingEnv::fully_monomorphized() + .as_query_input(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])), ) .unwrap(); Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout) @@ -341,7 +345,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { #[inline] #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980) - pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>)) -> (Self, Self) { + pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>)) -> (Self, Self) { let layout = self.layout; let (val0, val1) = self.to_scalar_pair(); ( @@ -773,8 +777,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { )?; if !mir_assign_valid_types( *self.tcx, - self.typing_mode(), - self.param_env, + self.typing_env(), self.layout_of(normalized_place_ty)?, op.layout, ) { @@ -833,9 +836,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }) }; let layout = - from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || { - self.layout_of(ty).into() - })?; + from_known_layout(self.tcx, self.typing_env(), layout, || self.layout_of(ty).into())?; let imm = match val_val { mir::ConstValue::Indirect { alloc_id, offset } => { // This is const data, no mutation allowed. diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index fbc85d37953..201f1b5dc62 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -533,7 +533,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } OffsetOf(fields) => { let val = - self.tcx.offset_of_subfield(self.param_env, layout, fields.iter()).bytes(); + self.tcx.offset_of_subfield(self.typing_env(), layout, fields.iter()).bytes(); ImmTy::from_uint(val, usize_layout()) } UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx), diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index cc8d1db6cfb..13fcccca76b 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -540,8 +540,7 @@ where )?; if !mir_assign_valid_types( *self.tcx, - self.typing_mode(), - self.param_env, + self.typing_env(), self.layout_of(normalized_place_ty)?, place.layout, ) { @@ -871,13 +870,8 @@ where ) -> InterpResult<'tcx> { // We do NOT compare the types for equality, because well-typed code can // actually "transmute" `&mut T` to `&T` in an assignment without a cast. - let layout_compat = mir_assign_valid_types( - *self.tcx, - self.typing_mode(), - self.param_env, - src.layout(), - dest.layout(), - ); + let layout_compat = + mir_assign_valid_types(*self.tcx, self.typing_env(), src.layout(), dest.layout()); if !allow_transmute && !layout_compat { span_bug!( self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 50c0446b3cd..037c1a233ee 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -379,7 +379,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { for &const_ in body.required_consts() { let c = self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?; - c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| { + c.eval(*self.tcx, self.typing_env(), const_.span).map_err(|err| { err.emit_note(*self.tcx); err })?; @@ -596,13 +596,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return interp_ok(layout); } - let layout = - from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || { - let local_ty = frame.body.local_decls[local].ty; - let local_ty = - self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?; - self.layout_of(local_ty).into() - })?; + let layout = from_known_layout(self.tcx, self.typing_env(), layout, || { + let local_ty = frame.body.local_decls[local].ty; + let local_ty = + self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?; + self.layout_of(local_ty).into() + })?; // Layouts of locals are requested a lot, so we cache them. state.layout.set(Some(layout)); diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 18cff2c5e0f..d4525243642 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -418,7 +418,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .collect::<InterpResult<'tcx, Vec<_>>>()?; let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx); - let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder); + let fn_sig = + self.tcx.normalize_erasing_late_bound_regions(self.typing_env(), fn_sig_binder); let extra_args = &args[fn_sig.inputs().len()..]; let extra_args = self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty)); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 3a68db9f7f7..005b430bc8a 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -448,7 +448,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { meta: MemPlaceMeta<M::Provenance>, pointee: TyAndLayout<'tcx>, ) -> InterpResult<'tcx> { - let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.param_env); + let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env()); match tail.kind() { ty::Dynamic(data, _, ty::Dyn) => { let vtable = meta.unwrap_meta().to_pointer(self.ecx)?; @@ -568,7 +568,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind }); }; let (size, _align) = - global_alloc.size_and_align(*self.ecx.tcx, self.ecx.param_env); + global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env()); if let GlobalAlloc::Static(did) = global_alloc { let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { @@ -955,7 +955,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { ) -> Cow<'e, RangeSet> { assert!(layout.ty.is_union()); assert!(layout.is_sized(), "there are no unsized unions"); - let layout_cx = LayoutCx::new(*ecx.tcx, ecx.param_env); + let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env()); return M::cached_union_data_range(ecx, layout.ty, || { let mut out = RangeSet(Vec::new()); union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out); diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 0490195caf4..527236b2c22 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -47,7 +47,7 @@ pub fn provide(providers: &mut Providers) { providers.hooks.try_destructure_mir_constant_for_user_output = const_eval::try_destructure_mir_constant_for_user_output; providers.valtree_to_const_val = |tcx, (ty, valtree)| { - const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree) + const_eval::valtree_to_const_value(tcx, ty::ParamEnv::reveal_all().and(ty), valtree) }; providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| { util::check_validity_requirement(tcx, init_kind, param_env_and_ty) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 6fa7d369229..9507b24f603 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -9,7 +9,7 @@ use tracing::debug; pub fn is_disaligned<'tcx, L>( tcx: TyCtxt<'tcx>, local_decls: &L, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, place: Place<'tcx>, ) -> bool where @@ -22,8 +22,8 @@ where }; let ty = place.ty(local_decls, tcx).ty; - let unsized_tail = || tcx.struct_tail_for_codegen(ty, param_env); - match tcx.layout_of(param_env.and(ty)) { + let unsized_tail = || tcx.struct_tail_for_codegen(ty, typing_env); + match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(layout) if layout.align.abi <= pack && (layout.is_sized() diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index f743525f359..1afc910ce8f 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -3,7 +3,7 @@ use rustc_middle::bug; use rustc_middle::ty::layout::{ HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement, }; -use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; +use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt}; use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine}; use crate::interpret::{InterpCx, MemoryKind}; @@ -23,16 +23,16 @@ use crate::interpret::{InterpCx, MemoryKind}; pub fn check_validity_requirement<'tcx>( tcx: TyCtxt<'tcx>, kind: ValidityRequirement, - param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>, + input: PseudoCanonicalInput<'tcx, Ty<'tcx>>, ) -> Result<bool, &'tcx LayoutError<'tcx>> { - let layout = tcx.layout_of(param_env_and_ty)?; + let layout = tcx.layout_of(input)?; // There is nothing strict or lax about inhabitedness. if kind == ValidityRequirement::Inhabited { return Ok(!layout.is_uninhabited()); } - let layout_cx = LayoutCx::new(tcx, param_env_and_ty.param_env); + let layout_cx = LayoutCx::new(tcx, input.typing_env); if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks { check_validity_requirement_strict(layout, &layout_cx, kind) } else { @@ -49,7 +49,7 @@ fn check_validity_requirement_strict<'tcx>( ) -> Result<bool, &'tcx LayoutError<'tcx>> { let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error); - let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.param_env, machine); + let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env.param_env, machine); let allocated = cx .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap)) diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs index 0cf27d30c36..9eed1a20f15 100644 --- a/compiler/rustc_const_eval/src/util/compare_types.rs +++ b/compiler/rustc_const_eval/src/util/compare_types.rs @@ -5,18 +5,17 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, TypingMode, Variance}; +use rustc_middle::ty::{Ty, TyCtxt, TypingEnv, Variance}; use rustc_trait_selection::traits::ObligationCtxt; /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`. pub fn sub_types<'tcx>( tcx: TyCtxt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, src: Ty<'tcx>, dest: Ty<'tcx>, ) -> bool { - relate_types(tcx, typing_mode, param_env, Variance::Covariant, src, dest) + relate_types(tcx, typing_env, Variance::Covariant, src, dest) } /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`. @@ -26,8 +25,7 @@ pub fn sub_types<'tcx>( /// because we want to check for type equality. pub fn relate_types<'tcx>( tcx: TyCtxt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, variance: Variance, src: Ty<'tcx>, dest: Ty<'tcx>, @@ -36,8 +34,7 @@ pub fn relate_types<'tcx>( return true; } - let mut builder = tcx.infer_ctxt().ignoring_regions(); - let infcx = builder.build(typing_mode); + let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env); let ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy(); let src = ocx.normalize(&cause, param_env, src); | 
