Skip to content

Commit d05bb98

Browse files
Extract borrowck coroutine drop-liveness hack
1 parent d525e79 commit d05bb98

File tree

2 files changed

+31
-19
lines changed

2 files changed

+31
-19
lines changed

compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
318318
})
319319
}
320320

321-
ty::Coroutine(_, args) => {
321+
ty::Coroutine(def_id, args) => {
322322
// rust-lang/rust#49918: types can be constructed, stored
323323
// in the interior, and sit idle when coroutine yields
324324
// (and is subsequently dropped).
@@ -346,7 +346,10 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
346346
// While we conservatively assume that all coroutines require drop
347347
// to avoid query cycles during MIR building, we can check the actual
348348
// witness during borrowck to avoid unnecessary liveness constraints.
349-
if args.witness().needs_drop(tcx, tcx.erase_regions(typing_env)) {
349+
let typing_env = tcx.erase_regions(typing_env);
350+
if tcx.mir_coroutine_witnesses(def_id).is_some_and(|witness| {
351+
witness.field_tys.iter().any(|field| field.ty.needs_drop(tcx, typing_env))
352+
}) {
350353
constraints.outlives.extend(args.upvar_tys().iter().map(ty::GenericArg::from));
351354
constraints.outlives.push(args.resume_ty().into());
352355
}

compiler/rustc_ty_utils/src/needs_drop.rs

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,6 @@ fn has_significant_drop_raw<'tcx>(
101101
struct NeedsDropTypes<'tcx, F> {
102102
tcx: TyCtxt<'tcx>,
103103
typing_env: ty::TypingEnv<'tcx>,
104-
/// Whether to reveal coroutine witnesses, this is set
105-
/// to `false` unless we compute `needs_drop` for a coroutine witness.
106-
reveal_coroutine_witnesses: bool,
107104
query_ty: Ty<'tcx>,
108105
seen_tys: FxHashSet<Ty<'tcx>>,
109106
/// A stack of types left to process, and the recursion depth when we
@@ -115,6 +112,15 @@ struct NeedsDropTypes<'tcx, F> {
115112
adt_components: F,
116113
/// Set this to true if an exhaustive list of types involved in
117114
/// drop obligation is requested.
115+
// FIXME: Calling this bool `exhaustive` is confusing and possibly a footgun,
116+
// since it does two things: It makes the iterator yield *all* of the types
117+
// that need drop, and it also affects the computation of the drop components
118+
// on `Coroutine`s. The latter is somewhat confusing, and probably should be
119+
// a function of `typing_env`. See the HACK comment below for why this is
120+
// necessary. If this isn't possible, then we probably should turn this into
121+
// a `NeedsDropMode` so that we can have a variant like `CollectAllSignificantDrops`,
122+
// which will more accurately indicate that we want *all* of the *significant*
123+
// drops, which are the two important behavioral changes toggled by this bool.
118124
exhaustive: bool,
119125
}
120126

@@ -131,7 +137,6 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
131137
Self {
132138
tcx,
133139
typing_env,
134-
reveal_coroutine_witnesses: exhaustive,
135140
seen_tys,
136141
query_ty: ty,
137142
unchecked_tys: vec![(ty, 0)],
@@ -195,23 +200,27 @@ where
195200
// for the coroutine witness and check whether any of the contained types
196201
// need to be dropped, and only require the captured types to be live
197202
// if they do.
198-
ty::Coroutine(_, args) => {
199-
if self.reveal_coroutine_witnesses {
200-
queue_type(self, args.as_coroutine().witness());
203+
ty::Coroutine(def_id, args) => {
204+
// FIXME: See FIXME on `exhaustive` field above.
205+
if self.exhaustive {
206+
for upvar in args.as_coroutine().upvar_tys() {
207+
queue_type(self, upvar);
208+
}
209+
queue_type(self, args.as_coroutine().resume_ty());
210+
if let Some(witness) = tcx.mir_coroutine_witnesses(def_id) {
211+
for field_ty in &witness.field_tys {
212+
queue_type(
213+
self,
214+
EarlyBinder::bind(field_ty.ty).instantiate(tcx, args),
215+
);
216+
}
217+
}
201218
} else {
202219
return Some(self.always_drop_component(ty));
203220
}
204221
}
205-
ty::CoroutineWitness(def_id, args) => {
206-
if let Some(witness) = tcx.mir_coroutine_witnesses(def_id) {
207-
self.reveal_coroutine_witnesses = true;
208-
for field_ty in &witness.field_tys {
209-
queue_type(
210-
self,
211-
EarlyBinder::bind(field_ty.ty).instantiate(tcx, args),
212-
);
213-
}
214-
}
222+
ty::CoroutineWitness(..) => {
223+
unreachable!("witness should be handled in parent");
215224
}
216225

217226
ty::UnsafeBinder(bound_ty) => {

0 commit comments

Comments
 (0)