Skip to content

Commit

Permalink
Fix the order of operands for generator structs (rust-lang#2436)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhassan-aws authored May 11, 2023
1 parent 708bc35 commit c3d28e0
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 3 deletions.
4 changes: 1 addition & 3 deletions kani-compiler/src/codegen_cprover_gotoc/codegen/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,6 @@ impl<'tcx> GotocCtx<'tcx> {
};
let overall_t = self.codegen_ty(ty);
let direct_fields = overall_t.lookup_field("direct_fields", &self.symbol_table).unwrap();
let mut operands_iter = operands.iter();
let direct_fields_expr = Expr::struct_expr_from_values(
direct_fields.typ(),
layout
Expand All @@ -342,13 +341,12 @@ impl<'tcx> GotocCtx<'tcx> {
if idx == *discriminant_field {
Expr::int_constant(0, self.codegen_ty(field_ty))
} else {
self.codegen_operand(operands_iter.next().unwrap())
self.codegen_operand(&operands[idx])
}
})
.collect(),
&self.symbol_table,
);
assert!(operands_iter.next().is_none());
Expr::union_expr(overall_t, "direct_fields", direct_fields_expr, &self.symbol_table)
}

Expand Down
53 changes: 53 additions & 0 deletions tests/kani/Generator/issue-2434.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
//
// compile-flags: --edition 2018

//! Regression test for https://github.com/model-checking/kani/issues/2434
//! The problem was an incorrect order for the operands
use core::{future::Future, pin::Pin};

type BoxFuture = Pin<Box<dyn Future<Output = ()> + Sync + 'static>>;

pub struct Scheduler {
task: Option<BoxFuture>,
}

impl Scheduler {
/// Adds a future to the scheduler's task list, returning a JoinHandle
pub fn spawn<F: Future<Output = ()> + Sync + 'static>(&mut self, fut: F) {
self.task = Some(Box::pin(fut));
}
}

/// Polls the given future and the tasks it may spawn until all of them complete
///
/// Contrary to block_on, this allows `spawn`ing other futures
pub fn spawnable_block_on<F: Future<Output = ()> + Sync + 'static>(
scheduler: &mut Scheduler,
fut: F,
) {
scheduler.spawn(fut);
}

/// Sender of a channel.
pub struct Sender {}

impl Sender {
pub async fn send(&self) {}
}

#[kani::proof]
fn check() {
let mut scheduler = Scheduler { task: None };
spawnable_block_on(&mut scheduler, async {
let num: usize = 1;
let tx = Sender {};

let _task1 = async move {
for _i in 0..num {
tx.send().await;
}
};
});
}

0 comments on commit c3d28e0

Please sign in to comment.