Skip to content

Commit c3d28e0

Browse files
authored
Fix the order of operands for generator structs (#2436)
1 parent 708bc35 commit c3d28e0

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

kani-compiler/src/codegen_cprover_gotoc/codegen/rvalue.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,6 @@ impl<'tcx> GotocCtx<'tcx> {
331331
};
332332
let overall_t = self.codegen_ty(ty);
333333
let direct_fields = overall_t.lookup_field("direct_fields", &self.symbol_table).unwrap();
334-
let mut operands_iter = operands.iter();
335334
let direct_fields_expr = Expr::struct_expr_from_values(
336335
direct_fields.typ(),
337336
layout
@@ -342,13 +341,12 @@ impl<'tcx> GotocCtx<'tcx> {
342341
if idx == *discriminant_field {
343342
Expr::int_constant(0, self.codegen_ty(field_ty))
344343
} else {
345-
self.codegen_operand(operands_iter.next().unwrap())
344+
self.codegen_operand(&operands[idx])
346345
}
347346
})
348347
.collect(),
349348
&self.symbol_table,
350349
);
351-
assert!(operands_iter.next().is_none());
352350
Expr::union_expr(overall_t, "direct_fields", direct_fields_expr, &self.symbol_table)
353351
}
354352

tests/kani/Generator/issue-2434.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
//
4+
// compile-flags: --edition 2018
5+
6+
//! Regression test for https://github.com/model-checking/kani/issues/2434
7+
//! The problem was an incorrect order for the operands
8+
use core::{future::Future, pin::Pin};
9+
10+
type BoxFuture = Pin<Box<dyn Future<Output = ()> + Sync + 'static>>;
11+
12+
pub struct Scheduler {
13+
task: Option<BoxFuture>,
14+
}
15+
16+
impl Scheduler {
17+
/// Adds a future to the scheduler's task list, returning a JoinHandle
18+
pub fn spawn<F: Future<Output = ()> + Sync + 'static>(&mut self, fut: F) {
19+
self.task = Some(Box::pin(fut));
20+
}
21+
}
22+
23+
/// Polls the given future and the tasks it may spawn until all of them complete
24+
///
25+
/// Contrary to block_on, this allows `spawn`ing other futures
26+
pub fn spawnable_block_on<F: Future<Output = ()> + Sync + 'static>(
27+
scheduler: &mut Scheduler,
28+
fut: F,
29+
) {
30+
scheduler.spawn(fut);
31+
}
32+
33+
/// Sender of a channel.
34+
pub struct Sender {}
35+
36+
impl Sender {
37+
pub async fn send(&self) {}
38+
}
39+
40+
#[kani::proof]
41+
fn check() {
42+
let mut scheduler = Scheduler { task: None };
43+
spawnable_block_on(&mut scheduler, async {
44+
let num: usize = 1;
45+
let tx = Sender {};
46+
47+
let _task1 = async move {
48+
for _i in 0..num {
49+
tx.send().await;
50+
}
51+
};
52+
});
53+
}

0 commit comments

Comments
 (0)