diff options
Diffstat (limited to 'compiler/rustc_ty_utils/src/needs_drop.rs')
-rw-r--r-- | compiler/rustc_ty_utils/src/needs_drop.rs | 58 |
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(_) => { |