Skip to content

Commit 85abb05

Browse files
committed
Rollup merge of #49194 - Zoxc:unsafe-generator, r=cramertj
Make resuming generators unsafe instead of the creation of immovable generators Fixes #47787
2 parents 101f7c2 + 57896ab commit 85abb05

30 files changed

+96
-124
lines changed

src/doc/unstable-book/src/language-features/generators.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ fn main() {
3636
return "foo"
3737
};
3838

39-
match generator.resume() {
39+
match unsafe { generator.resume() } {
4040
GeneratorState::Yielded(1) => {}
4141
_ => panic!("unexpected value from resume"),
4242
}
43-
match generator.resume() {
43+
match unsafe { generator.resume() } {
4444
GeneratorState::Complete("foo") => {}
4545
_ => panic!("unexpected value from resume"),
4646
}
@@ -69,9 +69,9 @@ fn main() {
6969
};
7070

7171
println!("1");
72-
generator.resume();
72+
unsafe { generator.resume() };
7373
println!("3");
74-
generator.resume();
74+
unsafe { generator.resume() };
7575
println!("5");
7676
}
7777
```
@@ -92,7 +92,7 @@ The `Generator` trait in `std::ops` currently looks like:
9292
pub trait Generator {
9393
type Yield;
9494
type Return;
95-
fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return>;
95+
unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return>;
9696
}
9797
```
9898

@@ -175,8 +175,8 @@ fn main() {
175175
return ret
176176
};
177177

178-
generator.resume();
179-
generator.resume();
178+
unsafe { generator.resume() };
179+
unsafe { generator.resume() };
180180
}
181181
```
182182

@@ -200,7 +200,7 @@ fn main() {
200200
type Yield = i32;
201201
type Return = &'static str;
202202

203-
fn resume(&mut self) -> GeneratorState<i32, &'static str> {
203+
unsafe fn resume(&mut self) -> GeneratorState<i32, &'static str> {
204204
use std::mem;
205205
match mem::replace(self, __Generator::Done) {
206206
__Generator::Start(s) => {
@@ -223,8 +223,8 @@ fn main() {
223223
__Generator::Start(ret)
224224
};
225225

226-
generator.resume();
227-
generator.resume();
226+
unsafe { generator.resume() };
227+
unsafe { generator.resume() };
228228
}
229229
```
230230

src/liballoc/boxed.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,7 @@ impl<T> Generator for Box<T>
892892
{
893893
type Yield = T::Yield;
894894
type Return = T::Return;
895-
fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
895+
unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
896896
(**self).resume()
897897
}
898898
}

src/libcore/ops/generator.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ pub enum GeneratorState<Y, R> {
5656
/// return "foo"
5757
/// };
5858
///
59-
/// match generator.resume() {
59+
/// match unsafe { generator.resume() } {
6060
/// GeneratorState::Yielded(1) => {}
6161
/// _ => panic!("unexpected return from resume"),
6262
/// }
63-
/// match generator.resume() {
63+
/// match unsafe { generator.resume() } {
6464
/// GeneratorState::Complete("foo") => {}
6565
/// _ => panic!("unexpected return from resume"),
6666
/// }
@@ -98,6 +98,10 @@ pub trait Generator {
9898
/// generator will continue executing until it either yields or returns, at
9999
/// which point this function will return.
100100
///
101+
/// The function is unsafe because it can be used on an immovable generator.
102+
/// After such a call, the immovable generator must not move again, but
103+
/// this is not enforced by the compiler.
104+
///
101105
/// # Return value
102106
///
103107
/// The `GeneratorState` enum returned from this function indicates what
@@ -116,7 +120,7 @@ pub trait Generator {
116120
/// been returned previously. While generator literals in the language are
117121
/// guaranteed to panic on resuming after `Complete`, this is not guaranteed
118122
/// for all implementations of the `Generator` trait.
119-
fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return>;
123+
unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return>;
120124
}
121125

122126
#[unstable(feature = "generator_trait", issue = "43122")]
@@ -125,7 +129,7 @@ impl<'a, T> Generator for &'a mut T
125129
{
126130
type Yield = T::Yield;
127131
type Return = T::Return;
128-
fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
132+
unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
129133
(**self).resume()
130134
}
131135
}

src/librustc_mir/diagnostics.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2247,7 +2247,7 @@ let mut b = || {
22472247
yield (); // ...is still in scope here, when the yield occurs.
22482248
println!("{}", a);
22492249
};
2250-
b.resume();
2250+
unsafe { b.resume() };
22512251
```
22522252
22532253
At present, it is not permitted to have a yield that occurs while a
@@ -2265,7 +2265,7 @@ let mut b = || {
22652265
yield ();
22662266
println!("{}", a);
22672267
};
2268-
b.resume();
2268+
unsafe { b.resume() };
22692269
```
22702270
22712271
This is a very simple case, of course. In more complex cases, we may
@@ -2283,7 +2283,7 @@ let mut b = || {
22832283
yield x; // ...when this yield occurs.
22842284
}
22852285
};
2286-
b.resume();
2286+
unsafe { b.resume() };
22872287
```
22882288
22892289
Such cases can sometimes be resolved by iterating "by value" (or using
@@ -2298,7 +2298,7 @@ let mut b = || {
22982298
yield x; // <-- Now yield is OK.
22992299
}
23002300
};
2301-
b.resume();
2301+
unsafe { b.resume() };
23022302
```
23032303
23042304
If taking ownership is not an option, using indices can work too:
@@ -2314,7 +2314,7 @@ let mut b = || {
23142314
yield x; // <-- Now yield is OK.
23152315
}
23162316
};
2317-
b.resume();
2317+
unsafe { b.resume() };
23182318
23192319
// (*) -- Unfortunately, these temporaries are currently required.
23202320
// See <https://github.com/rust-lang/rust/issues/43122>.

src/librustc_mir/transform/check_unsafety.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,21 +126,13 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
126126
&AggregateKind::Array(..) |
127127
&AggregateKind::Tuple |
128128
&AggregateKind::Adt(..) => {}
129-
&AggregateKind::Closure(def_id, _) => {
129+
&AggregateKind::Closure(def_id, _) |
130+
&AggregateKind::Generator(def_id, _, _) => {
130131
let UnsafetyCheckResult {
131132
violations, unsafe_blocks
132133
} = self.tcx.unsafety_check_result(def_id);
133134
self.register_violations(&violations, &unsafe_blocks);
134135
}
135-
&AggregateKind::Generator(def_id, _, interior) => {
136-
let UnsafetyCheckResult {
137-
violations, unsafe_blocks
138-
} = self.tcx.unsafety_check_result(def_id);
139-
self.register_violations(&violations, &unsafe_blocks);
140-
if !interior.movable {
141-
self.require_unsafe("construction of immovable generator")
142-
}
143-
}
144136
}
145137
}
146138
self.super_rvalue(rvalue, location);

src/test/run-pass/dynamic-drop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ fn generator(a: &Allocator, run_count: usize) {
179179
);
180180
};
181181
for _ in 0..run_count {
182-
gen.resume();
182+
unsafe { gen.resume(); }
183183
}
184184
}
185185

src/test/run-pass/generator/conditional-drop.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ fn t1() {
4242
};
4343

4444
let n = A.load(Ordering::SeqCst);
45-
a.resume();
45+
unsafe { a.resume() };
4646
assert_eq!(A.load(Ordering::SeqCst), n + 1);
47-
a.resume();
47+
unsafe { a.resume() };
4848
assert_eq!(A.load(Ordering::SeqCst), n + 1);
4949
}
5050

@@ -58,8 +58,8 @@ fn t2() {
5858
};
5959

6060
let n = A.load(Ordering::SeqCst);
61-
a.resume();
61+
unsafe { a.resume() };
6262
assert_eq!(A.load(Ordering::SeqCst), n);
63-
a.resume();
63+
unsafe { a.resume() };
6464
assert_eq!(A.load(Ordering::SeqCst), n + 1);
6565
}

src/test/run-pass/generator/control-flow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn finish<T>(mut amt: usize, mut t: T) -> T::Return
1616
where T: Generator<Yield = ()>
1717
{
1818
loop {
19-
match t.resume() {
19+
match unsafe { t.resume() } {
2020
GeneratorState::Yielded(()) => amt = amt.checked_sub(1).unwrap(),
2121
GeneratorState::Complete(ret) => {
2222
assert_eq!(amt, 0);

src/test/run-pass/generator/drop-env.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fn t1() {
3737
};
3838

3939
let n = A.load(Ordering::SeqCst);
40-
drop(foo.resume());
40+
drop(unsafe { foo.resume() });
4141
assert_eq!(A.load(Ordering::SeqCst), n);
4242
drop(foo);
4343
assert_eq!(A.load(Ordering::SeqCst), n + 1);
@@ -50,7 +50,7 @@ fn t2() {
5050
};
5151

5252
let n = A.load(Ordering::SeqCst);
53-
drop(foo.resume());
53+
drop(unsafe { foo.resume() });
5454
assert_eq!(A.load(Ordering::SeqCst), n + 1);
5555
drop(foo);
5656
assert_eq!(A.load(Ordering::SeqCst), n + 1);

src/test/run-pass/generator/issue-44197.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ fn bar2(baz: String) -> impl Generator<Yield = String, Return = ()> {
3535
}
3636

3737
fn main() {
38-
assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new()));
39-
assert_eq!(bar2(String::new()).resume(), GeneratorState::Complete(()));
38+
unsafe {
39+
assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new()));
40+
assert_eq!(bar2(String::new()).resume(), GeneratorState::Complete(()));
41+
}
4042
}

0 commit comments

Comments
 (0)