46 lines
1.2 KiB
Rust
46 lines
1.2 KiB
Rust
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
|
|
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
|
|
|
use std::{
|
|
ops::{Coroutine, CoroutineState},
|
|
pin::Pin,
|
|
};
|
|
|
|
fn firstn() -> impl Coroutine<Yield = u64, Return = ()> {
|
|
#[coroutine] static move || {
|
|
let mut num = 0;
|
|
let num = &mut num;
|
|
*num += 0;
|
|
|
|
yield *num;
|
|
*num += 1; //~ERROR: has been freed
|
|
}
|
|
}
|
|
|
|
struct CoroutineIteratorAdapter<G>(G);
|
|
|
|
impl<G> Iterator for CoroutineIteratorAdapter<G>
|
|
where
|
|
G: Coroutine<Return = ()>,
|
|
{
|
|
type Item = G::Yield;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
let me = unsafe { Pin::new_unchecked(&mut self.0) };
|
|
match me.resume(()) {
|
|
CoroutineState::Yielded(x) => Some(x),
|
|
CoroutineState::Complete(_) => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let mut coroutine_iterator_2 = {
|
|
let mut coroutine_iterator = Box::new(CoroutineIteratorAdapter(firstn()));
|
|
coroutine_iterator.next(); // pin it
|
|
|
|
Box::new(*coroutine_iterator) // move it
|
|
}; // *deallocate* coroutine_iterator
|
|
|
|
coroutine_iterator_2.next(); // and use moved value
|
|
}
|