about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2020-01-27 23:26:37 +0100
committerJonas Schievink <jonasschievink@gmail.com>2020-02-02 13:20:58 +0100
commit9fa46fe15367a8154f38371d0d913fa2f97f6416 (patch)
tree9d56ef3eb12ba3c4ce549a0e37b9b294417755e9
parentaae0f543cff16afe27384171e83de91887bc9f4d (diff)
downloadrust-9fa46fe15367a8154f38371d0d913fa2f97f6416.tar.gz
rust-9fa46fe15367a8154f38371d0d913fa2f97f6416.zip
Teach dropck about resume arguments
-rw-r--r--src/librustc_traits/dropck_outlives.rs5
-rw-r--r--src/test/ui/generator/dropck-resume.rs33
-rw-r--r--src/test/ui/generator/dropck-resume.stderr15
-rw-r--r--src/test/ui/generator/retain-resume-ref.stderr7
4 files changed, 55 insertions, 5 deletions
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index bc4d03cca7f..346d2a931d1 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -227,8 +227,8 @@ fn dtorck_constraint_for_ty<'tcx>(
             // 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.
+            // derived from lifetimes attached to the upvars and resume
+            // argument, and we *do* incorporate those here.
 
             constraints.outlives.extend(
                 substs
@@ -236,6 +236,7 @@ fn dtorck_constraint_for_ty<'tcx>(
                     .upvar_tys(def_id, tcx)
                     .map(|t| -> ty::subst::GenericArg<'tcx> { t.into() }),
             );
+            constraints.outlives.push(substs.as_generator().resume_ty(def_id, tcx).into());
         }
 
         ty::Adt(def, substs) => {
diff --git a/src/test/ui/generator/dropck-resume.rs b/src/test/ui/generator/dropck-resume.rs
new file mode 100644
index 00000000000..4c18077f335
--- /dev/null
+++ b/src/test/ui/generator/dropck-resume.rs
@@ -0,0 +1,33 @@
+#![feature(generators, generator_trait)]
+
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+struct SetToNone<'a: 'b, 'b>(&'b mut Option<&'a i32>);
+
+impl<'a, 'b> Drop for SetToNone<'a, 'b> {
+    fn drop(&mut self) {
+        *self.0 = None;
+    }
+}
+
+fn drop_using_generator() -> i32 {
+    let mut y = Some(&0);
+    let z = &mut y;
+    let r;
+    {
+        let mut g = move |r| {
+            let _s = SetToNone(r);
+            yield;
+        };
+        let mut g = Pin::new(&mut g);
+        g.as_mut().resume(z);
+        r = y.as_ref().unwrap();
+        //~^ ERROR cannot borrow `y` as immutable because it is also borrowed as mutable
+    }
+    **r
+}
+
+fn main() {
+    println!("{}", drop_using_generator());
+}
diff --git a/src/test/ui/generator/dropck-resume.stderr b/src/test/ui/generator/dropck-resume.stderr
new file mode 100644
index 00000000000..ecf92e7e3ae
--- /dev/null
+++ b/src/test/ui/generator/dropck-resume.stderr
@@ -0,0 +1,15 @@
+error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable
+  --> $DIR/dropck-resume.rs:25:13
+   |
+LL |     let z = &mut y;
+   |             ------ mutable borrow occurs here
+...
+LL |         r = y.as_ref().unwrap();
+   |             ^ immutable borrow occurs here
+LL |
+LL |     }
+   |     - mutable borrow might be used here, when `g` is dropped and runs the destructor for generator
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/generator/retain-resume-ref.stderr b/src/test/ui/generator/retain-resume-ref.stderr
index e33310d12d9..bc715c7030e 100644
--- a/src/test/ui/generator/retain-resume-ref.stderr
+++ b/src/test/ui/generator/retain-resume-ref.stderr
@@ -4,9 +4,10 @@ error[E0499]: cannot borrow `thing` as mutable more than once at a time
 LL |     gen.as_mut().resume(&mut thing);
    |                         ---------- first mutable borrow occurs here
 LL |     gen.as_mut().resume(&mut thing);
-   |                  ------ ^^^^^^^^^^ second mutable borrow occurs here
-   |                  |
-   |                  first borrow later used by call
+   |                         ^^^^^^^^^^ second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `gen` is dropped and runs the destructor for generator
 
 error: aborting due to previous error