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

Support for requires and ensures clauses #2555

Merged

Conversation

JustusAdam
Copy link
Contributor

@JustusAdam JustusAdam commented Jun 22, 2023

Description of changes:

Adds basic support for requires and ensures function contract macros.

Testing:

Some simple test cases have been added

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.

@JustusAdam JustusAdam changed the base branch from main to features/contracts June 22, 2023 20:26
@celinval
Copy link
Contributor

Can you please make sure the PR only include changes relevant to contract?

@JustusAdam JustusAdam changed the base branch from features/contracts to main June 22, 2023 23:12
@JustusAdam JustusAdam changed the base branch from main to features/contracts June 22, 2023 23:12
@JustusAdam
Copy link
Contributor Author

Yeah that was because the target branch was out of date.

Copy link
Contributor

@celinval celinval left a comment

Choose a reason for hiding this comment

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

That's great progress! As talked offline, the focus at this point is the CBMC integration. Here is a few notes:

  1. I think the bindings code look quite ready. :)
  2. Is there any reason why there is no tests for requires?
  3. For future PRs, I think it would be better if we make the compiler code more modular. We should also figure out what the user flow will be for contracts, so we can design the communication between each component.

cprover_bindings/src/goto_program/expr.rs Outdated Show resolved Hide resolved
cprover_bindings/src/goto_program/expr.rs Outdated Show resolved Hide resolved
cprover_bindings/src/goto_program/symbol.rs Outdated Show resolved Hide resolved
library/kani_macros/src/lib.rs Outdated Show resolved Hide resolved
library/kani_macros/src/lib.rs Outdated Show resolved Hide resolved
library/kani_macros/src/lib.rs Outdated Show resolved Hide resolved
library/kani_macros/src/lib.rs Show resolved Hide resolved
library/kani_macros/src/lib.rs Outdated Show resolved Hide resolved
tests/kani/FunctionContract/arbitrary_ensures_fail.rs Outdated Show resolved Hide resolved
@JustusAdam
Copy link
Contributor Author

  1. Is there any reason why there is no tests for requires?
  2. For future PRs, I think it would be better if we make the compiler code more modular. We should also figure out what the user flow will be for contracts, so we can design the communication between each component.

So they are actually related. I didn't add a test case for requires because I didn't implement substitution. But I realize that I can also add a test where the verification would fail if the precondition is violated (e.g. the assume did not take hold) so I'll do that.

And wrt. flow we've discussed that in person already but for the benefit of the log: The flow is in the design phase and will be added after history variables and quantifiers.

@JustusAdam
Copy link
Contributor Author

JustusAdam commented Jun 28, 2023

I need to mention here that this does a small change to the testing infrastructure as well. In particular a directory can now contain multiple "expected" tests. The setup is analogous to regular .rs tests but each also has an associated .expected file. The way that is implemented is that when looking for test in a directory and we find a candidate file my_file.rs then we first look for a file called my_file.expected as the expected file. If such a file exists then it will be used as the expected file, otherwise we look for a file with the name expected.

So this change is fully backwards compatible but also cuts down on potential directory spam for the "expected" tests and makes the behavior more intuitive wrt the documentation where it mentions .expected files.

@JustusAdam JustusAdam marked this pull request as ready for review June 29, 2023 01:48
@JustusAdam JustusAdam requested a review from a team as a code owner June 29, 2023 01:48
@JustusAdam JustusAdam self-assigned this Jun 29, 2023
@JustusAdam JustusAdam added this to the Function Contracts MVP milestone Jun 29, 2023
tests/kani/FunctionContract/simple_ensures_pass.rs Outdated Show resolved Hide resolved
tests/kani/FunctionContract/simple_ensures_fail.rs Outdated Show resolved Hide resolved
tests/kani/FunctionContract/arbitrary_ensures_fail.rs Outdated Show resolved Hide resolved
tests/kani/FunctionContract/arbitrary_ensures_pass.rs Outdated Show resolved Hide resolved
library/kani_macros/src/lib.rs Outdated Show resolved Hide resolved
kani-compiler/src/kani_middle/attributes.rs Show resolved Hide resolved
kani-compiler/src/kani_middle/attributes.rs Outdated Show resolved Hide resolved
kani-compiler/src/kani_middle/attributes.rs Outdated Show resolved Hide resolved
cprover_bindings/src/irep/irep_id.rs Outdated Show resolved Hide resolved
@feliperodri feliperodri changed the title Simple requires ensures Support for requires and ensures clauses Jul 6, 2023
Copy link
Contributor

@celinval celinval left a comment

Choose a reason for hiding this comment

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

For the feature branch, I think this is in a fairly good shape.

For the comments that reflect code quality / organization, for this PR, I think it's OK if you create an issue to capture the work and add a TODO statement with a description and a link to the new issue.

kani-compiler/src/kani_middle/attributes.rs Outdated Show resolved Hide resolved
kani-compiler/src/kani_middle/attributes.rs Outdated Show resolved Hide resolved
kani-compiler/src/kani_middle/attributes.rs Show resolved Hide resolved
kani-compiler/src/kani_middle/reachability.rs Outdated Show resolved Hide resolved
kani-driver/src/args/common.rs Outdated Show resolved Hide resolved
kani-driver/src/call_goto_instrument.rs Outdated Show resolved Hide resolved
kani-driver/src/call_goto_instrument.rs Outdated Show resolved Hide resolved
kani_metadata/src/harness.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@feliperodri feliperodri left a comment

Choose a reason for hiding this comment

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

LGTM.

@feliperodri
Copy link
Contributor

@celinval any idea why Cargo Audit is failing here?

@adpaco-aws
Copy link
Contributor

I think you just need to include the commit from #2581 in the source branch.

JustusAdam and others added 9 commits July 14, 2023 14:48
Adds pre- and postconditions
Co-authored-by: Celina G. Val <celinval@amazon.com>
Co-authored-by: Celina G. Val <celinval@amazon.com>
Added `requires` test case
Made tests `expected` tests
Changes `requires_ensures` macro to function
@JustusAdam
Copy link
Contributor Author

I did another rebase to try and address the audit issue. Tbh I should have merged instead but oh well. I am going to squash the commits before merging anyway at least that's the plan.

@JustusAdam
Copy link
Contributor Author

I'll bump the base branch next so the PR doesn't include the unrelated commits

@JustusAdam
Copy link
Contributor Author

JustusAdam commented Jul 20, 2023

I'm having trouble with this regression stuff now. The numbering for checks seems to be platform dependent and makes the test fail as a result? When I run on my machine the expected test suite completes fine but on the ubuntu CI it doesn't. What's the best practice here to make the expected output stable? Maybe @feliperodri can help?

@zhassan-aws
Copy link
Contributor

We don't include the check indices in the expected files to avoid those issues. Even if they're consistent across platforms, they may change with changes to the compiler or new CBMC versions. Note that compiletest checks for a substring and not an exact match for the line.

@JustusAdam
Copy link
Contributor Author

Does it require ordering? Because one thing I now worry about is that the expected success/failure may not be the one with the description I am looking for. E.g. if i expected one property to succeed and another to fail what guarantees me that "Status: FAILURE" actually belongs to my "Description: fail this" test and not my "Description: succeed this"?

@zhassan-aws
Copy link
Contributor

Does it require ordering?

Generally, no: the compiletest tool checks if each line in the expected file occurred in the output.

the expected success/failure may not be the one with the description I am looking for

If a line in the expected file ends in backslash, the following line must occur on the consecutive line in the output. This is how we achieve ordering (partially). See https://github.com/model-checking/kani/blob/main/tests/expected/assert-eq/expected for an example.

Changed tesdt runner to not leave trailing checks and to ignore whitespace around expected lines
@JustusAdam
Copy link
Contributor Author

I've fixed up the test cases but unfortunately benchcomp is still failing. Is that a problem?

@JustusAdam JustusAdam marked this pull request as draft July 23, 2023 02:23
@JustusAdam JustusAdam changed the base branch from features/contracts to main July 23, 2023 02:24
@JustusAdam JustusAdam changed the base branch from main to features/contracts July 23, 2023 02:24
@JustusAdam JustusAdam marked this pull request as ready for review July 23, 2023 02:24
@qinheping
Copy link
Contributor

qinheping commented Jul 23, 2023

There are some interesting founds in the Benchcomp CI.

  1. The running time of format/fmt_i8 in the old variant is ~2.62 seconds. However, it the past Benchcomp run, for example https://github.com/model-checking/kani/actions/runs/5558854620/job/15059090659#step:13:71, the running time of format/fmt_i8 is ~1000seconds.
  2. Also, the number_program_steps of the old variant of format/fmt_i8 and format_fmt/8 are much smaller than the number_program_steps of them in the table https://github.com/model-checking/kani/actions/runs/5627831808

The Benchcomp is comparing this PR with the old version after #2553 merged. So the performance regression accumulats from #2553 to now.

@qinheping
Copy link
Contributor

qinheping commented Jul 23, 2023

After comparing the Benchomp runs of these two commits https://github.com/model-checking/kani/actions/runs/5405839079/job/14637506427 and https://github.com/model-checking/kani/actions/runs/5459160729/job/14779199972.
I confirmed that the regression of all 6 regressed benchmarks
btreeset/insert_any/main btreeset/insert_same/main format/fmt_i8 s2n-quic/quic/s2n-quic-core/sync::cursor::tests::oracle_test
s2n-quic/quic/s2n-quic-core/sync::spsc::tests::alloc_test
s2n-quic/tools/xdp/s2n-quic-xdp/task::completion_to_tx::assign::tests::assignment_test
is due to the huge toolchain upgrade 7139063.
I don't think the failed Benchcomp run blocks this PR. But I think it is worth to revisit the toolchain upgrade to see if it is possible to recover the performance of these benchmarks.

Update: the regression of fmt_i8 was noticed and tracked in this issue #2576.

@feliperodri feliperodri merged commit 0d632c8 into model-checking:features/contracts Jul 24, 2023
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: No status
Development

Successfully merging this pull request may close these issues.

6 participants