summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ty_utils/src/needs_drop.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ty_utils/src/needs_drop.rs')
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs58
1 files changed, 30 insertions, 28 deletions
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 1fc5d9359..51a6d6235 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
use rustc_session::Limit;
-use rustc_span::{sym, DUMMY_SP};
+use rustc_span::sym;
use crate::errors::NeedsDropOverflow;
@@ -66,6 +66,9 @@ fn has_significant_drop_raw<'tcx>(
struct NeedsDropTypes<'tcx, F> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
+ // Whether to reveal coroutine witnesses, this is set
+ // to `false` unless we compute `needs_drop` for a coroutine witness.
+ reveal_coroutine_witnesses: bool,
query_ty: Ty<'tcx>,
seen_tys: FxHashSet<Ty<'tcx>>,
/// A stack of types left to process, and the recursion depth when we
@@ -89,6 +92,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
Self {
tcx,
param_env,
+ reveal_coroutine_witnesses: false,
seen_tys,
query_ty: ty,
unchecked_tys: vec![(ty, 0)],
@@ -133,8 +137,31 @@ where
// The information required to determine whether a generator has drop is
// computed on MIR, while this very method is used to build MIR.
// To avoid cycles, we consider that generators always require drop.
- ty::Generator(..) if tcx.sess.opts.unstable_opts.drop_tracking_mir => {
- return Some(Err(AlwaysRequiresDrop));
+ //
+ // HACK: Because we erase regions contained in the coroutine witness, we
+ // have to conservatively assume that every region captured by the
+ // coroutine has to be live when dropped. This results in a lot of
+ // undesirable borrowck errors. During borrowck, we call `needs_drop`
+ // for the coroutine witness and check whether any of the contained types
+ // need to be dropped, and only require the captured types to be live
+ // if they do.
+ ty::Generator(_, args, _) => {
+ if self.reveal_coroutine_witnesses {
+ queue_type(self, args.as_generator().witness());
+ } else {
+ return Some(Err(AlwaysRequiresDrop));
+ }
+ }
+ ty::GeneratorWitness(def_id, args) => {
+ if let Some(witness) = tcx.mir_generator_witnesses(def_id) {
+ self.reveal_coroutine_witnesses = true;
+ for field_ty in &witness.field_tys {
+ queue_type(
+ self,
+ EarlyBinder::bind(field_ty.ty).instantiate(tcx, args),
+ );
+ }
+ }
}
_ if component.is_copy_modulo_regions(tcx, self.param_env) => (),
@@ -145,29 +172,6 @@ where
}
}
- ty::Generator(def_id, args, _) => {
- let args = args.as_generator();
- for upvar in args.upvar_tys() {
- queue_type(self, upvar);
- }
-
- let witness = args.witness();
- let interior_tys = match witness.kind() {
- &ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys),
- _ => {
- tcx.sess.delay_span_bug(
- tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP),
- format!("unexpected generator witness type {witness:?}"),
- );
- return Some(Err(AlwaysRequiresDrop));
- }
- };
-
- for interior_ty in interior_tys {
- queue_type(self, interior_ty);
- }
- }
-
// Check for a `Drop` impl and whether this is a union or
// `ManuallyDrop`. If it's a struct or enum without a `Drop`
// impl then check whether the field types need `Drop`.
@@ -214,8 +218,6 @@ where
| ty::FnPtr(..)
| ty::Tuple(_)
| ty::Bound(..)
- | ty::GeneratorWitness(..)
- | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Infer(_)
| ty::Error(_) => {