Skip to content

Add support for function contracts in cprover_bindings. #1302

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

Merged
merged 29 commits into from
Jul 15, 2022

Conversation

monal
Copy link

@monal monal commented Jun 23, 2022

Description of changes:

Implement CodeWithContract type in cprover_bindings to generate Ireps of type Code but with additional fields for handling function contracts. Adds the #spec_requires and #spec_ensures clauses to the Irep.

Call-outs:

Added a new type Spec with field clauses:Vec<Expr> to store a list of boolean expressions that would serve as pre (or post) conditions on the function. This allows us to handle required #[PartialEq] trait for the clauses.

Testing:

  • How is this change tested?
    By running kani regression tests. As I haven't added the #[kani::requires] and #[kani::ensures] macros on the Rust side yet, it is not straightforward to add additional test cases right now.

  • Is this a refactor change?
    No.

Checklist

  • Each commit message has a non-empty body, explaining why the change was made
  • Methods or procedures are documented
  • Regression or unit tests are included, or existing tests cover the modified code
  • My PR is restricted to a single feature or bugfix

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.

@monal monal requested a review from a team as a code owner June 23, 2022 23:06
@celinval
Copy link
Contributor

Can you push this to a feature branch for now?

@tedinski
Copy link
Contributor

Can you push this to a feature branch for now?

I thought this was a mergeable unit, or nearly so, so I requested the PR.

I could see merging this as-is, or possibly with a unit test for the irep generation added. We don't yet have many (any?) unit tests for cprover_bindings, so this might be the first, but we do actually want to get tests against this crate and have to start somewhere. :)

@celinval
Copy link
Contributor

We already have unit tests in this crate. It would be great if we can add some food this code.

I would also suggest we tag the new functions with allow_dead with a link to the issue we're trying to solve.

@monal monal marked this pull request as draft June 27, 2022 16:23
@tautschnig
Copy link
Member

I note that as of moments ago diffblue/cbmc#6799 is merged, which means that function contracts now live in symbols of their own.

@monal
Copy link
Author

monal commented Jun 30, 2022

Thanks for linking the PR, @tautschnig! I will update my code accordingly.

@monal monal self-assigned this Jul 5, 2022
@monal monal changed the title Add CodeWithContract type to cprover_bindings for supporting function contracts. Add support for function contracts in cprover_bindings. Jul 6, 2022
@monal
Copy link
Author

monal commented Jul 6, 2022

Summary of changes:

  1. Add contract constructor to Symbol to create new symbols for function contracts.

  2. Store the contract information (preconditions, postconditions, assigns, etc.) in the value field of the symbol (on the goto-program side). Hence, add Contract(Contract) to ExprValue.
    During Irep generation, the contract's preconditions and postconditions are added to the type field under #spec_requires and #spec_ensures respectively.

  3. Add LambdaExpression and Tuple to Expr. They are mathematical expressions (Expressions that do not exist immediately in C) but adding them to Expr seems to be the best option right now. We can create a separate MathematicalExpr in the future, if needed.

    • The clauses in #spec_ensures(..) and #spec_requires(..) are wrapped in a lambda expression (using the as_lambda_expression method) to make sure that the contract symbol is self-contained and has a copy of the functions’ parameters. (Refer: CONTRACTS: store contracts in dedicated symbols diffblue/cbmc#6799).
    • The bound variables in a lambda expression are stored as a Tuple.
  4. Add MathematicalFunction to Type to store the type signature of lambda expressions.

@@ -104,6 +146,12 @@ pub struct Parameter {
base_name: Option<InternedString>,
}

/// Type for function contracts, loop contracts, etc.
#[derive(Debug, Clone)]
pub enum Contract {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be an enum?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it an enum to support different types of contracts. Like LoopContract(...) in the future. Is there an alternative way to do this?

@monal monal marked this pull request as ready for review July 8, 2022 19:53
@monal
Copy link
Author

monal commented Jul 8, 2022

  • Removed LambdaExpression and Tuple from Expr. Generating them at the Irep level now.
  • Added a module for Contract and introduced Spec to represent contract clauses.
  • Cleaned up whitespaces; added comments.

@monal monal requested a review from a team July 8, 2022 20:51
Copy link
Contributor

@zhassan-aws zhassan-aws left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@monal monal changed the base branch from main to features/function-contracts July 12, 2022 18:30
@@ -0,0 +1,56 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File comment to explain what contracts are and link to documentation

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comment + CBMC documentation link.

let name = name.into();
// Both base name and pretty name contain the name of the function that the contract is written for.
let base_name: InternedString = base_name.into();
let pretty_name = base_name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be the pretty name of the function? (We might have discussed this already)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the CBMC side, the pretty_name is still the name of the function and not the name of the contract. Should I set it to the contract's name instead?

id: IrepId::Lambda,
sub: vec![
tuple_irep(binding_variables, mm)
// For binding expressions (quantifies, let, lambda), the type of the `tuple_exprt` is set to just its ID in CBMC.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there other cases where this is different?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tuple_exprt has a constructor with a type argument. So, in CBMC, we can construct tuples with a specific type (and not just the ID). The binding_exprt that sits on top of a tuple_exprt always sets the type to be the ID.

@monal monal merged commit 751ad18 into model-checking:features/function-contracts Jul 15, 2022
zhassan-aws pushed a commit to zhassan-aws/kani that referenced this pull request May 26, 2023
…ng#1302)

* Add type for "spec_ensures" and "spec_requires" clauses to support function contracts

* Add transfomer code for code_with_contract; Fix comments; Minor implementation fixes

* Revert "Add transfomer code for code_with_contract; Fix comments; Minor implementation fixes"

This reverts commit f4afc15.

* Revert "Add type for "spec_ensures" and "spec_requires" clauses to support function contracts"

This reverts commit f7171f8.

* Move function contract to Symbol

* Revert "Move function contract to Symbol"

This reverts commit ffd3ad2.

* Add contract to SymbolValues

* Update SymbolValues::Contract to have expressions

* Add Contract type; Add Lambda and Tuple to Expr

* WIP: Add LambdaExpression and Tuple to Expr; Add MathematicalFunction to Type; Generate Ireps

* Update comment to explain pretty_name in contract symbol.

* Change type to slice

* Remove variables from FunctionContract type

* Add type checking to the lambda_expression constructor

* Change variables field in lambda expression to variables_tuple to avoid misreading the type

* Remove type annotations

* Remove LambdaExpression and Tuple

* Remove FunctionContract type

* Remove contracts

* WIP:Move contracts to a separate module; Add spec to handle Irep generation for contracts.

* WIP: Update spec to include location; Add comments

* WIP: Add comments

* WIP: Add location to spec

* WIP: remove whitespace

* WIP: Remove whitespace

* Add file comment

* Change Spec to always have Location

* format

Co-authored-by: Monal Narasimhamurthy <[email protected]>
zhassan-aws pushed a commit to zhassan-aws/kani that referenced this pull request May 26, 2023
…ng#1302)

* Add type for "spec_ensures" and "spec_requires" clauses to support function contracts

* Add transfomer code for code_with_contract; Fix comments; Minor implementation fixes

* Revert "Add transfomer code for code_with_contract; Fix comments; Minor implementation fixes"

This reverts commit f4afc15.

* Revert "Add type for "spec_ensures" and "spec_requires" clauses to support function contracts"

This reverts commit f7171f8.

* Move function contract to Symbol

* Revert "Move function contract to Symbol"

This reverts commit ffd3ad2.

* Add contract to SymbolValues

* Update SymbolValues::Contract to have expressions

* Add Contract type; Add Lambda and Tuple to Expr

* WIP: Add LambdaExpression and Tuple to Expr; Add MathematicalFunction to Type; Generate Ireps

* Update comment to explain pretty_name in contract symbol.

* Change type to slice

* Remove variables from FunctionContract type

* Add type checking to the lambda_expression constructor

* Change variables field in lambda expression to variables_tuple to avoid misreading the type

* Remove type annotations

* Remove LambdaExpression and Tuple

* Remove FunctionContract type

* Remove contracts

* WIP:Move contracts to a separate module; Add spec to handle Irep generation for contracts.

* WIP: Update spec to include location; Add comments

* WIP: Add comments

* WIP: Add location to spec

* WIP: remove whitespace

* WIP: Remove whitespace

* Add file comment

* Change Spec to always have Location

* format

Co-authored-by: Monal Narasimhamurthy <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

6 participants