-
Notifications
You must be signed in to change notification settings - Fork 116
Assertion failure in check_vtable_size
#1593
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This also occurs in
And in
|
Example without dependencies (~130 lines) that I hit while working on #1504: use std::{
sync::{
atomic::{AtomicI64, Ordering},
Arc,
},
future::Future,
pin::Pin,
task::{Context, RawWaker, RawWakerVTable, Waker},
};
const NOOP_RAW_WAKER: RawWaker = {
#[inline]
unsafe fn clone_waker(_: *const ()) -> RawWaker {
NOOP_RAW_WAKER
}
#[inline]
unsafe fn noop(_: *const ()) {}
RawWaker::new(
std::ptr::null(),
&RawWakerVTable::new(clone_waker, noop, noop, noop),
)
};
type BoxFuture = Pin<Box<dyn Future<Output = ()>>>;
static mut GLOBAL_EXECUTOR: SpawnOnceScheduler = SpawnOnceScheduler::new();
struct SpawnOnceScheduler
{
spawner: Option<BoxFuture>,
spawnee: Option<BoxFuture>,
}
impl SpawnOnceScheduler
{
pub const fn new() -> Self {
Self {
spawner: None,
spawnee: None,
}
}
pub fn spawn(&mut self, fut: impl Future<Output = ()> + 'static) {
let _ = std::mem::replace(&mut self.spawnee, Some(Box::pin(fut)));
}
pub fn run(&mut self) {
let waker = unsafe { Waker::from_raw(NOOP_RAW_WAKER) };
let cx = &mut Context::from_waker(&waker);
let mut index = 0;
while self.spawner.is_some() || self.spawnee.is_some() {
index = (index + 1) % 2;
if index == 0 {
Self::poll_task(&mut self.spawner, cx)
} else {
Self::poll_task(&mut self.spawnee, cx)
}
}
}
fn poll_task(task: &mut Option<BoxFuture>, cx: &mut Context) {
if let Some(fut) = task.as_mut() {
match fut.as_mut().poll(cx) {
std::task::Poll::Ready(_) => {
let _ = std::mem::replace(task, None);
}
std::task::Poll::Pending => (),
}
}
}
pub fn block_on(
self: &'static mut Self,
fut: impl Future<Output = ()> + 'static,
) {
let _ = std::mem::replace(&mut self.spawner, Some(Box::pin(fut)));
self.run();
}
}
pub fn spawn<F: Future<Output = ()> + Sync + 'static>(fut: F) {
unsafe { GLOBAL_EXECUTOR.spawn(fut) }
}
pub fn spawnable_block_on(
fut: impl Future<Output = ()> + 'static,
) {
unsafe { GLOBAL_EXECUTOR.block_on(fut) }
}
struct YieldNow {
yielded: bool,
}
impl Future for YieldNow {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> std::task::Poll<Self::Output> {
if self.yielded {
cx.waker().wake_by_ref(); // For completeness. But Kani currently ignores wakers.
std::task::Poll::Ready(())
} else {
self.yielded = true;
std::task::Poll::Pending
}
}
}
pub fn yield_now() -> impl Future<Output = ()> {
YieldNow { yielded: false }
}
#[cfg_attr(kani, kani::proof)]
#[cfg_attr(kani, kani::unwind(4))]
fn nondeterministic_schedule() {
let x = Arc::new(AtomicI64::new(0)); // Surprisingly, Arc verified faster than Rc
let x2 = x.clone();
spawnable_block_on(
async move {
yield_now().await;
x2.fetch_add(1, Ordering::Relaxed);
},
);
assert_eq!(x.load(Ordering::Relaxed), 2);
} Run it like this: Result:
|
I believe this issue has similar root cause as #1395. The failure is triggered while trying to create a vtable for a generator wrapper:
I.e.: This code is converting We fail because the size of |
Reproduction steps:
That "current codegen location" is here:
The text was updated successfully, but these errors were encountered: