Skip to content

Commit dc46a7f

Browse files
authored
Rollup merge of rust-lang#69935 - davidtwco:issue-69925, r=eddyb
codegen/mir: support polymorphic `InstanceDef`s cc rust-lang#69925 This PR modifies the use of `subst_and_normalize_erasing_regions` on parts of the MIR bodies returned from `instance_mir`, so that `InstanceDef::CloneShim` and `InstanceDef::DropGlue` (where there is a type) do not perform substitutions. This avoids double substitutions and enables polymorphic `InstanceDef`s. r? @eddyb cc @nikomatsakis
2 parents 50656db + bee1513 commit dc46a7f

File tree

7 files changed

+102
-83
lines changed

7 files changed

+102
-83
lines changed

src/librustc/ty/instance.rs

+26
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,32 @@ impl<'tcx> Instance<'tcx> {
381381
Instance { def, substs }
382382
}
383383

384+
/// FIXME(#69925) Depending on the kind of `InstanceDef`, the MIR body associated with an
385+
/// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other
386+
/// cases the MIR body is expressed in terms of the types found in the substitution array.
387+
/// In the former case, we want to substitute those generic types and replace them with the
388+
/// values from the substs when monomorphizing the function body. But in the latter case, we
389+
/// don't want to do that substitution, since it has already been done effectively.
390+
///
391+
/// This function returns `Some(substs)` in the former case and None otherwise -- i.e., if
392+
/// this function returns `None`, then the MIR body does not require substitution during
393+
/// monomorphization.
394+
pub fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> {
395+
match self.def {
396+
InstanceDef::CloneShim(..)
397+
| InstanceDef::DropGlue(_, Some(_)) => None,
398+
InstanceDef::ClosureOnceShim { .. }
399+
| InstanceDef::DropGlue(..)
400+
// FIXME(#69925): `FnPtrShim` should be in the other branch.
401+
| InstanceDef::FnPtrShim(..)
402+
| InstanceDef::Item(_)
403+
| InstanceDef::Intrinsic(..)
404+
| InstanceDef::ReifyShim(..)
405+
| InstanceDef::Virtual(..)
406+
| InstanceDef::VtableShim(..) => Some(self.substs),
407+
}
408+
}
409+
384410
pub fn is_vtable_shim(&self) -> bool {
385411
if let InstanceDef::VtableShim(..) = self.def { true } else { false }
386412
}

src/librustc_codegen_ssa/mir/mod.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,18 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
8686
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
8787
pub fn monomorphize<T>(&self, value: &T) -> T
8888
where
89-
T: TypeFoldable<'tcx>,
89+
T: Copy + TypeFoldable<'tcx>,
9090
{
91-
self.cx.tcx().subst_and_normalize_erasing_regions(
92-
self.instance.substs,
93-
ty::ParamEnv::reveal_all(),
94-
value,
95-
)
91+
debug!("monomorphize: self.instance={:?}", self.instance);
92+
if let Some(substs) = self.instance.substs_for_mir_body() {
93+
self.cx.tcx().subst_and_normalize_erasing_regions(
94+
substs,
95+
ty::ParamEnv::reveal_all(),
96+
&value,
97+
)
98+
} else {
99+
self.cx.tcx().normalize_erasing_regions(ty::ParamEnv::reveal_all(), *value)
100+
}
96101
}
97102
}
98103

src/librustc_mir/interpret/eval_context.rs

+17-10
Original file line numberDiff line numberDiff line change
@@ -335,15 +335,25 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
335335

336336
/// Call this on things you got out of the MIR (so it is as generic as the current
337337
/// stack frame), to bring it into the proper environment for this interpreter.
338+
pub(super) fn subst_from_current_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
339+
&self,
340+
value: T,
341+
) -> T {
342+
self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value)
343+
}
344+
345+
/// Call this on things you got out of the MIR (so it is as generic as the provided
346+
/// stack frame), to bring it into the proper environment for this interpreter.
338347
pub(super) fn subst_from_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
339348
&self,
349+
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
340350
value: T,
341351
) -> T {
342-
self.tcx.subst_and_normalize_erasing_regions(
343-
self.frame().instance.substs,
344-
self.param_env,
345-
&value,
346-
)
352+
if let Some(substs) = frame.instance.substs_for_mir_body() {
353+
self.tcx.subst_and_normalize_erasing_regions(substs, self.param_env, &value)
354+
} else {
355+
self.tcx.normalize_erasing_regions(self.param_env, value)
356+
}
347357
}
348358

349359
/// The `substs` are assumed to already be in our interpreter "universe" (param_env).
@@ -371,11 +381,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
371381
None => {
372382
let layout = crate::interpret::operand::from_known_layout(layout, || {
373383
let local_ty = frame.body.local_decls[local].ty;
374-
let local_ty = self.tcx.subst_and_normalize_erasing_regions(
375-
frame.instance.substs,
376-
self.param_env,
377-
&local_ty,
378-
);
384+
let local_ty =
385+
self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty);
379386
self.layout_of(local_ty)
380387
})?;
381388
if let Some(state) = frame.locals.get(local) {

src/librustc_mir/interpret/operand.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
490490
Copy(ref place) | Move(ref place) => self.eval_place_to_op(place, layout)?,
491491

492492
Constant(ref constant) => {
493-
let val = self.subst_from_frame_and_normalize_erasing_regions(constant.literal);
493+
let val =
494+
self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal);
494495
self.eval_const_to_op(val, layout)?
495496
}
496497
};

src/librustc_mir/interpret/place.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -640,9 +640,11 @@ where
640640
// bail out.
641641
None => Place::null(&*self),
642642
},
643-
layout: self.layout_of(self.subst_from_frame_and_normalize_erasing_regions(
644-
self.frame().body.return_ty(),
645-
))?,
643+
layout: self.layout_of(
644+
self.subst_from_current_frame_and_normalize_erasing_regions(
645+
self.frame().body.return_ty(),
646+
),
647+
)?,
646648
}
647649
}
648650
local => PlaceTy {

src/librustc_mir/interpret/step.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
248248
}
249249

250250
NullaryOp(mir::NullOp::SizeOf, ty) => {
251-
let ty = self.subst_from_frame_and_normalize_erasing_regions(ty);
251+
let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
252252
let layout = self.layout_of(ty)?;
253253
assert!(
254254
!layout.is_unsized(),

src/librustc_mir/monomorphize/collector.rs

+40-62
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ use rustc::mir::visit::Visitor as MirVisitor;
185185
use rustc::mir::{self, Local, Location};
186186
use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast};
187187
use rustc::ty::print::obsolete::DefPathBasedNames;
188-
use rustc::ty::subst::{InternalSubsts, SubstsRef};
188+
use rustc::ty::subst::InternalSubsts;
189189
use rustc::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable};
190190
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
191191
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
@@ -493,7 +493,21 @@ struct MirNeighborCollector<'a, 'tcx> {
493493
tcx: TyCtxt<'tcx>,
494494
body: &'a mir::Body<'tcx>,
495495
output: &'a mut Vec<MonoItem<'tcx>>,
496-
param_substs: SubstsRef<'tcx>,
496+
instance: Instance<'tcx>,
497+
}
498+
499+
impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> {
500+
pub fn monomorphize<T>(&self, value: T) -> T
501+
where
502+
T: TypeFoldable<'tcx>,
503+
{
504+
debug!("monomorphize: self.instance={:?}", self.instance);
505+
if let Some(substs) = self.instance.substs_for_mir_body() {
506+
self.tcx.subst_and_normalize_erasing_regions(substs, ty::ParamEnv::reveal_all(), &value)
507+
} else {
508+
self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), value)
509+
}
510+
}
497511
}
498512

499513
impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
@@ -509,17 +523,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
509523
ref operand,
510524
target_ty,
511525
) => {
512-
let target_ty = self.tcx.subst_and_normalize_erasing_regions(
513-
self.param_substs,
514-
ty::ParamEnv::reveal_all(),
515-
&target_ty,
516-
);
526+
let target_ty = self.monomorphize(target_ty);
517527
let source_ty = operand.ty(self.body, self.tcx);
518-
let source_ty = self.tcx.subst_and_normalize_erasing_regions(
519-
self.param_substs,
520-
ty::ParamEnv::reveal_all(),
521-
&source_ty,
522-
);
528+
let source_ty = self.monomorphize(source_ty);
523529
let (source_ty, target_ty) =
524530
find_vtable_types_for_unsizing(self.tcx, source_ty, target_ty);
525531
// This could also be a different Unsize instruction, like
@@ -540,11 +546,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
540546
_,
541547
) => {
542548
let fn_ty = operand.ty(self.body, self.tcx);
543-
let fn_ty = self.tcx.subst_and_normalize_erasing_regions(
544-
self.param_substs,
545-
ty::ParamEnv::reveal_all(),
546-
&fn_ty,
547-
);
549+
let fn_ty = self.monomorphize(fn_ty);
548550
visit_fn_use(self.tcx, fn_ty, false, &mut self.output);
549551
}
550552
mir::Rvalue::Cast(
@@ -553,11 +555,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
553555
_,
554556
) => {
555557
let source_ty = operand.ty(self.body, self.tcx);
556-
let source_ty = self.tcx.subst_and_normalize_erasing_regions(
557-
self.param_substs,
558-
ty::ParamEnv::reveal_all(),
559-
&source_ty,
560-
);
558+
let source_ty = self.monomorphize(source_ty);
561559
match source_ty.kind {
562560
ty::Closure(def_id, substs) => {
563561
let instance = Instance::resolve_closure(
@@ -593,7 +591,23 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
593591
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
594592
debug!("visiting const {:?} @ {:?}", *constant, location);
595593

596-
collect_const(self.tcx, *constant, self.param_substs, self.output);
594+
let substituted_constant = self.monomorphize(*constant);
595+
let param_env = ty::ParamEnv::reveal_all();
596+
597+
match substituted_constant.val {
598+
ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
599+
ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
600+
match self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
601+
Ok(val) => collect_const_value(self.tcx, val, self.output),
602+
Err(ErrorHandled::Reported) => {}
603+
Err(ErrorHandled::TooGeneric) => span_bug!(
604+
self.tcx.def_span(def_id),
605+
"collection encountered polymorphic constant",
606+
),
607+
}
608+
}
609+
_ => {}
610+
}
597611

598612
self.super_const(constant);
599613
}
@@ -605,21 +619,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
605619
match *kind {
606620
mir::TerminatorKind::Call { ref func, .. } => {
607621
let callee_ty = func.ty(self.body, tcx);
608-
let callee_ty = tcx.subst_and_normalize_erasing_regions(
609-
self.param_substs,
610-
ty::ParamEnv::reveal_all(),
611-
&callee_ty,
612-
);
622+
let callee_ty = self.monomorphize(callee_ty);
613623
visit_fn_use(self.tcx, callee_ty, true, &mut self.output);
614624
}
615625
mir::TerminatorKind::Drop { ref location, .. }
616626
| mir::TerminatorKind::DropAndReplace { ref location, .. } => {
617627
let ty = location.ty(self.body, self.tcx).ty;
618-
let ty = tcx.subst_and_normalize_erasing_regions(
619-
self.param_substs,
620-
ty::ParamEnv::reveal_all(),
621-
&ty,
622-
);
628+
let ty = self.monomorphize(ty);
623629
visit_drop_use(self.tcx, ty, true, self.output);
624630
}
625631
mir::TerminatorKind::Goto { .. }
@@ -1156,8 +1162,7 @@ fn collect_neighbours<'tcx>(
11561162
debug!("collect_neighbours: {:?}", instance.def_id());
11571163
let body = tcx.instance_mir(instance.def);
11581164

1159-
MirNeighborCollector { tcx, body: &body, output, param_substs: instance.substs }
1160-
.visit_body(body);
1165+
MirNeighborCollector { tcx, body: &body, output, instance }.visit_body(body);
11611166
}
11621167

11631168
fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String {
@@ -1167,33 +1172,6 @@ fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String {
11671172
output
11681173
}
11691174

1170-
fn collect_const<'tcx>(
1171-
tcx: TyCtxt<'tcx>,
1172-
constant: &'tcx ty::Const<'tcx>,
1173-
param_substs: SubstsRef<'tcx>,
1174-
output: &mut Vec<MonoItem<'tcx>>,
1175-
) {
1176-
debug!("visiting const {:?}", constant);
1177-
1178-
let param_env = ty::ParamEnv::reveal_all();
1179-
let substituted_constant =
1180-
tcx.subst_and_normalize_erasing_regions(param_substs, param_env, &constant);
1181-
1182-
match substituted_constant.val {
1183-
ty::ConstKind::Value(val) => collect_const_value(tcx, val, output),
1184-
ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
1185-
match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
1186-
Ok(val) => collect_const_value(tcx, val, output),
1187-
Err(ErrorHandled::Reported) => {}
1188-
Err(ErrorHandled::TooGeneric) => {
1189-
span_bug!(tcx.def_span(def_id), "collection encountered polymorphic constant",)
1190-
}
1191-
}
1192-
}
1193-
_ => {}
1194-
}
1195-
}
1196-
11971175
fn collect_const_value<'tcx>(
11981176
tcx: TyCtxt<'tcx>,
11991177
value: ConstValue<'tcx>,

0 commit comments

Comments
 (0)