Skip to content

Make DropShim's param_env optional to fix InstanceKind::DropShim #127815

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

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 24 additions & 12 deletions compiler/rustc_mir_dataflow/src/elaborate_drops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ty::ParamEnv<'tcx>>;

// Drop logic

Expand Down Expand Up @@ -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)
})
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_dataflow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_mir_transform/src/coroutine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_transform/src/elaborate_drops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ty::ParamEnv<'tcx>> {
Some(self.ctxt.param_env())
}

#[instrument(level = "debug", skip(self), ret)]
Expand Down
35 changes: 2 additions & 33 deletions compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
use rustc_session::config::{DebugInfo, OptLevel};
use rustc_span::source_map::Spanned;
use rustc_span::sym;
Expand Down Expand Up @@ -207,7 +205,7 @@ impl<'tcx> Inliner<'tcx> {
}
}

let callee_body = try_instance_mir(self.tcx, callsite.callee.def)?;
let callee_body = self.tcx.instance_mir(callsite.callee.def);
self.check_mir_body(callsite, callee_body, callee_attrs, cross_crate_inlinable)?;

if !self.tcx.consider_optimizing(|| {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1100,26 +1089,6 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
}
}

#[instrument(skip(tcx), level = "debug")]
fn try_instance_mir<'tcx>(
tcx: TyCtxt<'tcx>,
instance: InstanceKind<'tcx>,
) -> Result<&'tcx Body<'tcx>, &'static str> {
if let ty::InstanceKind::DropGlue(_, Some(ty))
| ty::InstanceKind::AsyncDropGlueCtorShim(_, Some(ty)) = instance
&& let ty::Adt(def, args) = ty.kind()
{
let fields = def.all_fields();
for field in fields {
let field_ty = field.ty(tcx, args);
if field_ty.has_param() && field_ty.has_aliases() {
return Err("cannot build drop shim for polymorphic type");
}
}
}
Ok(tcx.instance_mir(instance))
}

fn body_is_forwarder(body: &Body<'_>) -> bool {
let TerminatorKind::Call { target, .. } = body.basic_blocks[START_BLOCK].terminator().kind
else {
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_mir_transform/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -276,7 +276,8 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)

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);
Expand Down Expand Up @@ -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<ty::ParamEnv<'tcx>>,
}

impl fmt::Debug for DropShimElaborator<'_, '_> {
Expand All @@ -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<ty::ParamEnv<'tcx>> {
self.param_env
}

Expand Down
Loading