From 56d99aca8b754af36921012477096cad026cac1c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 16 Jul 2024 11:19:29 -0400 Subject: [PATCH] Make param-env optional in drop elaboration --- .../rustc_mir_dataflow/src/elaborate_drops.rs | 36 ++++++++++++------- compiler/rustc_mir_dataflow/src/lib.rs | 1 + compiler/rustc_mir_transform/src/coroutine.rs | 3 +- .../src/elaborate_drops.rs | 4 +-- compiler/rustc_mir_transform/src/inline.rs | 13 +------ compiler/rustc_mir_transform/src/shim.rs | 9 ++--- 6 files changed, 35 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 2ec3b53bc9814..0827b5ac6d24d 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -111,7 +111,11 @@ pub trait DropElaborator<'a, 'tcx>: fmt::Debug { fn patch(&mut self) -> &mut MirPatch<'tcx>; fn body(&self) -> &'a Body<'tcx>; fn tcx(&self) -> TyCtxt<'tcx>; - fn param_env(&self) -> ty::ParamEnv<'tcx>; + + // A param-env that can be used to compute drop queries (such as `Ty::needs_drop`). + // If this is `None`, then the elaborator must handle the type as if it were unknown, + // i.e. emitting full drops. + fn param_env(&self) -> Option>; // Drop logic @@ -276,9 +280,11 @@ where let subpath = self.elaborator.field_subpath(variant_path, field); let tcx = self.tcx(); - assert_eq!(self.elaborator.param_env().reveal(), Reveal::All); - let field_ty = - tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, args)); + let mut field_ty = f.ty(tcx, args); + if let Some(param_env) = self.elaborator.param_env() { + assert_eq!(param_env.reveal(), Reveal::All); + field_ty = tcx.normalize_erasing_regions(param_env, field_ty); + } (tcx.mk_place_field(base_place, field, field_ty), subpath) }) @@ -374,9 +380,9 @@ where debug!("drop_ladder({:?}, {:?})", self, fields); let mut fields = fields; - fields.retain(|&(place, _)| { - self.place_ty(place).needs_drop(self.tcx(), self.elaborator.param_env()) - }); + if let Some(param_env) = self.elaborator.param_env() { + fields.retain(|&(place, _)| self.place_ty(place).needs_drop(self.tcx(), param_env)); + } debug!("drop_ladder - fields needing drop: {:?}", fields); @@ -548,10 +554,13 @@ where have_otherwise = true; let param_env = self.elaborator.param_env(); - let have_field_with_drop_glue = variant - .fields - .iter() - .any(|field| field.ty(tcx, args).needs_drop(tcx, param_env)); + + let have_field_with_drop_glue = param_env.is_none_or(|param_env| { + variant + .fields + .iter() + .any(|field| field.ty(tcx, args).needs_drop(tcx, param_env)) + }); if have_field_with_drop_glue { have_otherwise_with_drop_glue = true; } @@ -869,7 +878,10 @@ where ty::Adt(def, args) => self.open_drop_for_adt(*def, args), ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind), ty::Array(ety, size) => { - let size = size.try_eval_target_usize(self.tcx(), self.elaborator.param_env()); + let size = self + .elaborator + .param_env() + .and_then(|param_env| size.try_eval_target_usize(self.tcx(), param_env)); self.open_drop_for_array(*ety, size) } ty::Slice(ety) => self.drop_loop_pair(*ety), diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index b0808ba2067e3..4c783bdb7eb44 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -2,6 +2,7 @@ #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(exact_size_is_empty)] +#![feature(is_none_or)] #![feature(let_chains)] #![feature(try_blocks)] // tidy-alphabetical-end diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 82528109be9ab..1228f4cfccb8b 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1174,7 +1174,8 @@ fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); let param_env = tcx.param_env(def_id); - let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env }; + let mut elaborator = + DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env: Some(param_env) }; for (block, block_data) in body.basic_blocks.iter_enumerated() { let (target, unwind, source_info) = match block_data.terminator() { diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 5a22ef7790349..acb87aafb8bae 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -161,8 +161,8 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, '_, 'tcx> { self.ctxt.tcx } - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.ctxt.param_env() + fn param_env(&self) -> Option> { + Some(self.ctxt.param_env()) } #[instrument(level = "debug", skip(self), ret)] diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index f30732e6aaf3b..7c0ff27fa2fa5 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -12,9 +12,7 @@ use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::{ - self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt, TypeFlags, TypeVisitableExt, -}; +use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::config::{DebugInfo, OptLevel}; use rustc_span::source_map::Spanned; use rustc_span::sym; @@ -323,15 +321,6 @@ impl<'tcx> Inliner<'tcx> { return Err("instance without MIR (intrinsic / virtual)"); } - // FIXME(#127030): `ConstParamHasTy` has bad interactions with - // the drop shim builder, which does not evaluate predicates in - // the correct param-env for types being dropped. Stall resolving - // the MIR for this instance until all of its const params are - // substituted. - InstanceKind::DropGlue(_, Some(ty)) if ty.has_type_flags(TypeFlags::HAS_CT_PARAM) => { - return Err("still needs substitution"); - } - // This cannot result in an immediate cycle since the callee MIR is a shim, which does // not get any optimizations run on it. Any subsequent inlining may cause cycles, but we // do not need to catch this here, we can wait until the inliner decides to continue diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index f41f3ef656c51..41cfcc005b49a 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -9,7 +9,7 @@ use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, GenericArgs, Ty, TyCtxt, + self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeVisitableExt, }; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle}; @@ -276,7 +276,8 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) if ty.is_some() { let patch = { - let param_env = tcx.param_env_reveal_all_normalized(def_id); + let param_env = + if ty.has_non_region_param() { None } else { Some(ty::ParamEnv::reveal_all()) }; let mut elaborator = DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, param_env }; let dropee = tcx.mk_place_deref(dropee_ptr); @@ -336,7 +337,7 @@ pub struct DropShimElaborator<'a, 'tcx> { pub body: &'a Body<'tcx>, pub patch: MirPatch<'tcx>, pub tcx: TyCtxt<'tcx>, - pub param_env: ty::ParamEnv<'tcx>, + pub param_env: Option>, } impl fmt::Debug for DropShimElaborator<'_, '_> { @@ -357,7 +358,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn param_env(&self) -> ty::ParamEnv<'tcx> { + fn param_env(&self) -> Option> { self.param_env }