Skip to content

Commit 9fa46fe

Browse files
Teach dropck about resume arguments
1 parent aae0f54 commit 9fa46fe

File tree

4 files changed

+55
-5
lines changed

4 files changed

+55
-5
lines changed

src/librustc_traits/dropck_outlives.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -227,15 +227,16 @@ fn dtorck_constraint_for_ty<'tcx>(
227227
// In particular, skipping over `_interior` is safe
228228
// because any side-effects from dropping `_interior` can
229229
// only take place through references with lifetimes
230-
// derived from lifetimes attached to the upvars, and we
231-
// *do* incorporate the upvars here.
230+
// derived from lifetimes attached to the upvars and resume
231+
// argument, and we *do* incorporate those here.
232232

233233
constraints.outlives.extend(
234234
substs
235235
.as_generator()
236236
.upvar_tys(def_id, tcx)
237237
.map(|t| -> ty::subst::GenericArg<'tcx> { t.into() }),
238238
);
239+
constraints.outlives.push(substs.as_generator().resume_ty(def_id, tcx).into());
239240
}
240241

241242
ty::Adt(def, substs) => {
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#![feature(generators, generator_trait)]
2+
3+
use std::ops::{Generator, GeneratorState};
4+
use std::pin::Pin;
5+
6+
struct SetToNone<'a: 'b, 'b>(&'b mut Option<&'a i32>);
7+
8+
impl<'a, 'b> Drop for SetToNone<'a, 'b> {
9+
fn drop(&mut self) {
10+
*self.0 = None;
11+
}
12+
}
13+
14+
fn drop_using_generator() -> i32 {
15+
let mut y = Some(&0);
16+
let z = &mut y;
17+
let r;
18+
{
19+
let mut g = move |r| {
20+
let _s = SetToNone(r);
21+
yield;
22+
};
23+
let mut g = Pin::new(&mut g);
24+
g.as_mut().resume(z);
25+
r = y.as_ref().unwrap();
26+
//~^ ERROR cannot borrow `y` as immutable because it is also borrowed as mutable
27+
}
28+
**r
29+
}
30+
31+
fn main() {
32+
println!("{}", drop_using_generator());
33+
}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable
2+
--> $DIR/dropck-resume.rs:25:13
3+
|
4+
LL | let z = &mut y;
5+
| ------ mutable borrow occurs here
6+
...
7+
LL | r = y.as_ref().unwrap();
8+
| ^ immutable borrow occurs here
9+
LL |
10+
LL | }
11+
| - mutable borrow might be used here, when `g` is dropped and runs the destructor for generator
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0502`.

src/test/ui/generator/retain-resume-ref.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ error[E0499]: cannot borrow `thing` as mutable more than once at a time
44
LL | gen.as_mut().resume(&mut thing);
55
| ---------- first mutable borrow occurs here
66
LL | gen.as_mut().resume(&mut thing);
7-
| ------ ^^^^^^^^^^ second mutable borrow occurs here
8-
| |
9-
| first borrow later used by call
7+
| ^^^^^^^^^^ second mutable borrow occurs here
8+
LL |
9+
LL | }
10+
| - first borrow might be used here, when `gen` is dropped and runs the destructor for generator
1011

1112
error: aborting due to previous error
1213

0 commit comments

Comments
 (0)