Skip to content
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

Loop Contracts Annotation for While-Loop #3151

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
0e49d50
Loop Contracts Annotation for While-Loop
qinheping Apr 19, 2024
a5cc42c
Bump dependencies and Kani's version to 0.50.0 (#3148)
celinval Apr 17, 2024
537eefc
Upgrade toolchain to 2024-04-18 and improve toolchain workflow (#3149)
celinval Apr 18, 2024
4806dac
Automatic toolchain upgrade to nightly-2024-04-19 (#3150)
github-actions[bot] Apr 19, 2024
55e5f0d
Stabilize cover statement and update contracts RFC (#3091)
celinval Apr 19, 2024
0e6c192
Automatic toolchain upgrade to nightly-2024-04-20 (#3154)
github-actions[bot] Apr 22, 2024
dd6e60f
Bump tests/perf/s2n-quic from `2d5e891` to `5f88e54` (#3140)
dependabot[bot] Apr 22, 2024
a542ede
Automatic cargo update to 2024-04-22 (#3157)
github-actions[bot] Apr 22, 2024
3cf110c
Automatic toolchain upgrade to nightly-2024-04-21 (#3158)
github-actions[bot] Apr 22, 2024
4be4214
Bump tests/perf/s2n-quic from `5f88e54` to `9730578` (#3159)
dependabot[bot] Apr 22, 2024
e5b0a2a
Fix cargo audit error (#3160)
jaisnan Apr 22, 2024
b244770
Fix cbmc-update CI job (#3156)
tautschnig Apr 23, 2024
ec29ffd
Automatic cargo update to 2024-04-29 (#3165)
github-actions[bot] Apr 29, 2024
1371195
Bump tests/perf/s2n-quic from `9730578` to `1436af7` (#3166)
dependabot[bot] Apr 29, 2024
5d64679
Do not assume that ZST-typed symbols refer to unique objects (#3134)
tautschnig Apr 30, 2024
7bc0cb8
Fix copyright check for `expected` tests (#3170)
adpaco-aws May 3, 2024
df2c1fb
Remove kani::Arbitrary from the modifies contract instrumentation (#3…
feliperodri May 3, 2024
5edab5d
Annotate loop contracts as statement expression
qinheping May 9, 2024
c8ecefe
Automatic cargo update to 2024-05-06 (#3172)
github-actions[bot] May 6, 2024
bda1f3c
Bump tests/perf/s2n-quic from `1436af7` to `6dd41e0` (#3174)
dependabot[bot] May 6, 2024
eaf5b42
Avoid unnecessary uses of Location::none() (#3173)
tautschnig May 7, 2024
cf5a8f9
Update Rust dependencies (#3175)
karkhaz May 7, 2024
584a3de
Bump Kani version to 0.51.0 (#3176)
karkhaz May 7, 2024
195c453
Merge branch 'main' into features/loop-contracts-annotation
qinheping May 9, 2024
52878c5
Remove leftover code
qinheping May 9, 2024
6547dcd
Remove unused import
qinheping May 9, 2024
319a8b9
Fix format
qinheping May 9, 2024
2569af0
Loop invariants should be operands of named subs
qinheping May 9, 2024
36c7628
Merge branch 'main' into features/loop-contracts-annotation
qinheping Aug 6, 2024
159e6ad
Allow cloned reachability checks
qinheping Aug 6, 2024
fbd17d6
Fix format
qinheping Aug 6, 2024
1a81de2
Fix format
qinheping Aug 7, 2024
3596dbe
Apply Adrian's comments
qinheping Aug 13, 2024
5210107
Use with_loop_contracts
qinheping Aug 13, 2024
54168fd
Fix tests
qinheping Aug 13, 2024
def6b97
Merge branch 'main' into features/loop-contracts-annotation
qinheping Sep 3, 2024
64b66d3
Fix format
qinheping Sep 3, 2024
0b05968
Refactor the loop contracts with closures
qinheping Sep 11, 2024
3624655
Add missing copyright
qinheping Sep 11, 2024
3a481a0
Merge branch 'main' into features/loop-contracts-annotation
qinheping Sep 11, 2024
68554df
Use proc_macro_error2
qinheping Sep 11, 2024
75a82d5
Provide locals to ty()
qinheping Sep 11, 2024
20b8de0
Do loop contracts transformation only for harnesses
qinheping Sep 11, 2024
c82684e
Merge branch 'main' into features/loop-contracts-annotation
qinheping Sep 20, 2024
90c1c5c
Move loop-contracts-hook and add more documentation
qinheping Sep 20, 2024
608baeb
Fix format
qinheping Sep 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions library/kani/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,25 @@ pub const fn assert(cond: bool, msg: &'static str) {
#[rustc_diagnostic_item = "KaniCover"]
pub const fn cover(_cond: bool, _msg: &'static str) {}

/// This function is only used for loop contract annotation.
/// It behaves as a placeholder to telling us where is the loop head and loop end
/// that we want to annotate to.
#[inline(never)]
qinheping marked this conversation as resolved.
Show resolved Hide resolved
#[rustc_diagnostic_item = "KaniLoopInvariant"]
pub const fn kani_loop_invariant(_cond: bool) {}
qinheping marked this conversation as resolved.
Show resolved Hide resolved

/// This function is only used for loop contract annotation.
/// It behaves as a placeholder to telling us where the loop invariants stmts begin.
#[inline(never)]
#[rustc_diagnostic_item = "KaniLoopInvariantBegin"]
pub const fn kani_loop_invariant_begin() {}

/// This function is only used for loop contract annotation.
/// It behaves as a placeholder to telling us where the loop invariants stmts end.
#[inline(never)]
#[rustc_diagnostic_item = "KaniLoopInvariantEnd"]
pub const fn kani_loop_invariant_end() {}

/// This creates an symbolic *valid* value of type `T`. You can assign the return value of this
/// function to a variable that you want to make symbolic.
///
Expand Down
84 changes: 84 additions & 0 deletions library/kani_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ mod derive;
use proc_macro::TokenStream;
use proc_macro_error::proc_macro_error;

use proc_macro2::TokenStream as TokenStream2;

#[cfg(kani_sysroot)]
use sysroot as attr_impl;

use proc_macro2::{Ident, Span};
#[cfg(not(kani_sysroot))]
use regular as attr_impl;
use syn::{Expr, Stmt};

/// Marks a Kani proof harness
///
Expand Down Expand Up @@ -198,6 +202,13 @@ pub fn modifies(attr: TokenStream, item: TokenStream) -> TokenStream {
attr_impl::modifies(attr, item)
}

#[proc_macro_attribute]
pub fn loop_invariant(attr: TokenStream, item: TokenStream) -> TokenStream {
qinheping marked this conversation as resolved.
Show resolved Hide resolved
attr_impl::loop_invariant(attr, item)
}

static mut LOOP_INVARIANT_COUNT: u32 = 0;
qinheping marked this conversation as resolved.
Show resolved Hide resolved

/// This module implements Kani attributes in a way that only Kani's compiler can understand.
/// This code should only be activated when pre-building Kani's sysroot.
#[cfg(kani_sysroot)]
Expand All @@ -206,6 +217,7 @@ mod sysroot {

mod contracts;

use contracts::helpers::*;
pub use contracts::{ensures, modifies, proof_for_contract, requires, stub_verified};

use super::*;
Expand Down Expand Up @@ -346,6 +358,77 @@ mod sysroot {
kani_attribute!(stub);
kani_attribute!(unstable);
kani_attribute!(unwind);

pub fn loop_invariant(attr: TokenStream, item: TokenStream) -> TokenStream {
qinheping marked this conversation as resolved.
Show resolved Hide resolved
// Update the loop counter to distinguish loop invariants for different loops.
unsafe {
LOOP_INVARIANT_COUNT += 1;
}
qinheping marked this conversation as resolved.
Show resolved Hide resolved

let mut loop_stmt: Stmt = syn::parse(item.clone()).unwrap();
// Parse the loop invariant expression.
let inv_expr: Expr = chunks_by(TokenStream2::from(attr.clone()), is_token_stream_2_comma)
.map(syn::parse2::<Expr>)
.filter_map(|expr| match expr {
Err(_) => None,
Ok(expr) => Some(expr),
})
.collect::<Vec<_>>()[0]
.clone();

// Annotate a place holder function call
// kani::kani_loop_invariant()
// at the end of the loop.
match loop_stmt {
Stmt::Expr(ref mut e, _) => match e {
Expr::While(ref mut ew) => {
// A while loop of the form
// ``` rust
// while guard {
// body
// }
// ```
// is annotated as
// ``` rust
// kani::kani_loop_invariant_begin();
// let __kani_loop_invariant_1 = ||(inv);
// kani::kani_loop_invariant_end();
// while guard{
// body
// kani::kani_loop_invariant(true);
// }
// ```
let end_stmt: Stmt = syn::parse(
quote!(
kani::kani_loop_invariant(true);)
.into(),
)
.unwrap();
ew.body.stmts.push(end_stmt);
}
_ => (),
},
_ => todo!("implement support for loops other than while loops."),
qinheping marked this conversation as resolved.
Show resolved Hide resolved
}

// instrument the invariants as a closure,
// and the call to the closure between two placeholders
// TODO: all variables in inv_expr should be reference.
unsafe {
let closre_name = Ident::new(
qinheping marked this conversation as resolved.
Show resolved Hide resolved
&format!("__kani_loop_invariant_{LOOP_INVARIANT_COUNT}"),
Span::call_site(),
);
quote!(
let #closre_name = ||(#inv_expr);
qinheping marked this conversation as resolved.
Show resolved Hide resolved
kani::kani_loop_invariant_begin();
#closre_name();
kani::kani_loop_invariant_end();
#loop_stmt
qinheping marked this conversation as resolved.
Show resolved Hide resolved
)
.into()
}
}
}

/// This module provides dummy implementations of Kani attributes which cannot be interpreted by
Expand Down Expand Up @@ -384,4 +467,5 @@ mod regular {
no_op!(modifies);
no_op!(proof_for_contract);
no_op!(stub_verified);
no_op!(loop_invariant);
}
2 changes: 1 addition & 1 deletion library/kani_macros/src/sysroot/contracts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ use syn::{parse_macro_input, Expr, ItemFn};

mod bootstrap;
mod check;
mod helpers;
pub mod helpers;
mod initialize;
mod replace;
mod shared;
Expand Down
Loading