Skip to content

Commit 0819c05

Browse files
Replicate live variant drop elaboration during const-checking
1 parent c85779c commit 0819c05

File tree

1 file changed

+47
-2
lines changed

1 file changed

+47
-2
lines changed

src/librustc_mir/transform/check_consts/post_drop_elaboration.rs

+47-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ use super::ops;
88
use super::qualifs::{NeedsDrop, Qualif};
99
use super::validation::Qualifs;
1010
use super::ConstCx;
11+
use crate::dataflow::drop_flag_effects::on_all_drop_children_bits;
12+
use crate::dataflow::move_paths::MoveData;
13+
use crate::dataflow::{self, Analysis, MoveDataParamEnv, ResultsCursor};
1114

1215
/// Returns `true` if we should use the more precise live drop checker that runs after drop
1316
/// elaboration.
@@ -31,14 +34,22 @@ pub fn check_live_drops(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &mir::Body<
3134

3235
let ccx = ConstCx { body, tcx, def_id, const_kind, param_env: tcx.param_env(def_id) };
3336

34-
let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };
37+
let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default(), maybe_inits: None };
3538

3639
visitor.visit_body(body);
3740
}
3841

42+
type MaybeInits<'mir, 'tcx> = ResultsCursor<
43+
'mir,
44+
'tcx,
45+
dataflow::impls::MaybeInitializedPlaces<'mir, 'tcx, MoveDataParamEnv<'tcx>>,
46+
>;
47+
3948
struct CheckLiveDrops<'mir, 'tcx> {
4049
ccx: &'mir ConstCx<'mir, 'tcx>,
4150
qualifs: Qualifs<'mir, 'tcx>,
51+
52+
maybe_inits: Option<MaybeInits<'mir, 'tcx>>,
4253
}
4354

4455
// So we can access `body` and `tcx`.
@@ -83,7 +94,41 @@ impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> {
8394
return;
8495
}
8596

86-
if self.qualifs.needs_drop(self.ccx, dropped_place.local, location) {
97+
if !self.qualifs.needs_drop(self.ccx, dropped_place.local, location) {
98+
return;
99+
}
100+
101+
let ConstCx { param_env, body, tcx, def_id, .. } = *self.ccx;
102+
103+
// Replicate some logic from drop elaboration during const-checking. If we know
104+
// that the active variant of an enum does not have drop glue, we can allow it to
105+
// be dropped.
106+
let maybe_inits = self.maybe_inits.get_or_insert_with(|| {
107+
let move_data = MoveData::gather_moves(body, tcx, param_env).unwrap();
108+
let mdpe = MoveDataParamEnv { move_data, param_env };
109+
dataflow::impls::MaybeInitializedPlaces::new(tcx, body, mdpe)
110+
.mark_inactive_variants_as_uninit(true)
111+
.into_engine(tcx, body, def_id.to_def_id())
112+
.iterate_to_fixpoint()
113+
.into_results_cursor(body)
114+
});
115+
maybe_inits.seek_before_primary_effect(location);
116+
let mdpe = &maybe_inits.analysis().mdpe;
117+
118+
let dropped_mpi = mdpe
119+
.move_data
120+
.rev_lookup
121+
.find(dropped_place.as_ref())
122+
.expect_exact("All dropped places should have a move path");
123+
124+
let mut is_live_drop = false;
125+
on_all_drop_children_bits(tcx, body, mdpe, dropped_mpi, |mpi| {
126+
if maybe_inits.contains(mpi) {
127+
is_live_drop = true;
128+
}
129+
});
130+
131+
if is_live_drop {
87132
// Use the span where the dropped local was declared for the error.
88133
let span = self.body.local_decls[dropped_place.local].source_info.span;
89134
self.check_live_drop(span);

0 commit comments

Comments
 (0)