diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index bc4d03cca7fe..346d2a931d10 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 000000000000..4c18077f3357 --- /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 000000000000..ecf92e7e3ae7 --- /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 e33310d12d9e..bc715c7030eb 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