about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2018-04-13 17:11:53 +0200
committerFelix S. Klock II <pnkfelix@pnkfx.org>2018-05-01 22:28:54 +0200
commitedb8d1c0d4b2e32088f3c6a77437b091b10ddf7e (patch)
tree004215cfb42495e6a8e8fea5ff93889140f90d50
parent4d7bbdd82682b0c4891538b241f7fe584f148710 (diff)
downloadrust-edb8d1c0d4b2e32088f3c6a77437b091b10ddf7e.tar.gz
rust-edb8d1c0d4b2e32088f3c6a77437b091b10ddf7e.zip
Conservatively assume dropping a generator touches its upvars, via locals' dtors.
This is meant to address rust-lang/rust#49918.

Review feedback: put back comment justifying skipping interior traversal.

Review feedback: dropck generators like trait objects: all their upvars must
outlive the generator itself, so just create a DtorckConstraint saying so.
-rw-r--r--src/librustc_traits/dropck_outlives.rs40
1 files changed, 32 insertions, 8 deletions
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 5f4daf0d568..ba31ce2692f 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -193,14 +193,38 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
             .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
             .collect(),
 
-        ty::TyGenerator(def_id, substs, _) => {
-            // Note that the interior types are ignored here.
-            // Any type reachable inside the interior must also be reachable
-            // through the upvars.
-            substs
-                .upvar_tys(def_id, tcx)
-                .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
-                .collect()
+        ty::TyGenerator(def_id, substs, _interior) => {
+            // rust-lang/rust#49918: types can be constructed, stored
+            // in the interior, and sit idle when generator yields
+            // (and is subsequently dropped).
+            //
+            // It would be nice to descend into interior of a
+            // generator to determine what effects dropping it might
+            // have (by looking at any drop effects associated with
+            // its interior).
+            //
+            // However, the interior's representation uses things like
+            // TyGeneratorWitness that explicitly assume they are not
+            // traversed in such a manner. So instead, we will
+            // simplify things for now by treating all generators as
+            // if they were like trait objects, where its upvars must
+            // all be alive for the generator's (potential)
+            // destructor.
+            //
+            // In particular, skipping over `_interior` is safe
+            // because any side-effects from dropping `_interior` can
+            // only take place through references with lifetimes
+            // derived from lifetimes attached to the upvars, and we
+            // *do* incorporate the upvars here.
+
+            let constraint = DtorckConstraint {
+                outlives: substs.upvar_tys(def_id, tcx).map(|t| t.into()).collect(),
+                dtorck_types: vec![],
+                overflows: vec![],
+            };
+            debug!("dtorck_constraint: generator {:?} => {:?}", def_id, constraint);
+
+            Ok(constraint)
         }
 
         ty::TyAdt(def, substs) => {