Skip to content

Conversation

@AlexanderPortland
Copy link
Contributor

@AlexanderPortland AlexanderPortland commented Jul 15, 2025

This discusses a prototype implementation of the feature suggested in #3006 that would allow users to soundly partition proofs into harnesses that could be verified separately and in parallel.

Rendered

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

@AlexanderPortland AlexanderPortland requested a review from a team as a code owner July 15, 2025 18:04
@carolynzech carolynzech self-requested a review July 15, 2025 18:24
@carolynzech carolynzech self-assigned this Jul 15, 2025
Copy link
Contributor

@carolynzech carolynzech left a comment

Choose a reason for hiding this comment

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

Thanks! First round of comments. Remember to update SUMMARY.md!

Copy link
Member

@tautschnig tautschnig left a comment

Choose a reason for hiding this comment

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

The various comments need to be driven to a conclusion, but I'm certainly supportive of the overall idea.

@tautschnig tautschnig removed their assignment Jul 16, 2025
@AlexanderPortland
Copy link
Contributor Author

Carolyn and I just had a talk about the syntax thoughts discussed above and echoed by Sammy here, and we started to converge on an idea that seems compelling. (Just dumping our thoughts here now until I have time to edit the RFC at a later date)

The initial syntax of kani::partition([i > 0, i < 0], || target_fn(input)) has some great benefits, mainly a) tying the partition conditions directly to the part of the proof being partitioned (rather than associating them with the whole harness) and b) maintaining the very logical idiom that harnesses don't take any arguments.

However, this syntax also brings up some questions, such as how a condition like i > 0 knows that it's operating over the input variable without relying solely on them sharing an ident, and how to ensure that input is filtered to be within the bounds of the partition after it has already been captured by the || target_fn(input) closure.

To fix this, we discussed a new API where partition would be a function Kani users can call with the following signature. The compiler would then detect this call within a proof, and generate the multiple partition harnesses, with each kani::assume-ing for a different one of the partition conditions.

pub fn partition<T: Arbitrary, R, const N: usize>(
    variable: T,
    conditions: [fn(&T) -> bool; N],
    and_run: fn(T) -> R,
) -> R {
    // This inner code will likely be a compiler intrinsic, 
    // but is just included to get a sense of the logical shape for now
    let partition_num = /* DEPENDS ON PARTITION */;
    kani::assume(conditions[partition_num](&variable));
    and_run(variable)
}

Which could be called along the lines of

#[kani::proof]
pub fn partitioned_harness2() {
    let input = kani::any();
    let r = kani::partition(input, [|a| *a > 10, ...], |input| target_fn(input));
}

Some key notes:

  • for now, both the conditions and and_run variables are function pointers, which forces them to not capture any variables. Allowing capturing of non-deterministic values (e.g. those generated with kani::any()) feels like it could lead to correctness issues, but this may be an overapproximation of a fix.
  • for now, the T: Arbitrary bound ensures partitioning can only be done on types that can be generated from kani::any()--that seems like the most clear set of use cases. However, it may eventually be useful to relax that restriction in some cases where a non-Arbitrary value is generated from an Arbitrary one, and i makes more sense for the partition to be defined on the latter.
  • we'd likely want to prevent multiple calls to kani::partition within the same proof, as this could lead to exponential growth in the number of generated harnesses

(Will add these to the RFC's open questions when I have time)

@AlexanderPortland
Copy link
Contributor Author

When working on a second draft of this RFC, I encountered a potential issue with the above syntax. Consider the following proof harness:

#[kani::proof]
pub fn strange_partitioned_harness() {
    let input: i32 = kani::any();

    let f: fn(&i32) -> bool = if input > 10 {
        |a: &i32| *a < 0
    } else {
        |a: &i32| *a < -2
    };

    kani::partition(input, [f, |a| *a >= 0], |i| target_fn(i));
}

Since one of the partition conditions depends on the non-deterministic partition variable, it seems almost non-sensical, as partition conditions should just be pre-defined filters to split that variable, rather than a function determined by runtime values.

To fix this, I tried forcing the conditions array to be compile-time evaluable by making it a const generic (with the signature below), but then the compiler complained saying "the type of const parameters must not depend on other generic parameters".

pub fn partition<T: kani::Arbitrary, R, const N: usize, const C: [fn(&T) -> bool; N]>(
    variable: T,
    conditions: C,
    and_run: fn(T) -> R,
) -> R

Is there a better way to ensure that the value of the function pointers we get can't be impacted by non-det values?

@AlexanderPortland
Copy link
Contributor Author

Second draft of this RFC! Note that in discussion w/ @carolynzech and @camelid, the issue raised in my comment above should be fixed in this newly proposed API if we also check the validity of partition conditions.

@AlexanderPortland AlexanderPortland changed the title RFC: Partitioned harnesses RFC: Partitioned proofs Jul 23, 2025
Copy link
Contributor

@carolynzech carolynzech left a comment

Choose a reason for hiding this comment

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

Thanks! This is looking great.

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.

Nice, thanks! Some minor comments.

@AlexanderPortland AlexanderPortland added this pull request to the merge queue Aug 21, 2025
Merged via the queue into model-checking:main with commit 8b8b897 Aug 21, 2025
32 of 33 checks passed
@AlexanderPortland AlexanderPortland deleted the harness-partitioning-rfc branch August 21, 2025 22:22
github-merge-queue bot pushed a commit that referenced this pull request Nov 6, 2025
Raw release notes:
```
## What's Changed
* Automatic toolchain upgrade to nightly-2025-08-07 by @github-actions[bot] in #4278
* Add loop invariant support for `while let` loop  by @thanhnguyen-aws in #4279
* Automatic toolchain upgrade to nightly-2025-08-08 by @github-actions[bot] in #4281
* Automatic toolchain upgrade to nightly-2025-08-09 by @github-actions[bot] in #4283
* Automatic cargo update to 2025-08-11 by @github-actions[bot] in #4285
* Bump tests/perf/s2n-quic from `8f510f0` to `c64faf9` by @dependabot[bot] in #4288
* Bump actions/checkout from 4 to 5 by @dependabot[bot] in #4286
* Bump actions/download-artifact from 4 to 5 by @dependabot[bot] in #4287
* Upgrade toolchain to 2025-08-10 by @carolynzech in #4289
* Automatic toolchain upgrade to nightly-2025-08-11 by @github-actions[bot] in #4290
* Automatic toolchain upgrade to nightly-2025-08-12 by @github-actions[bot] in #4292
* Update README by @carolynzech in #4291
* Automatic toolchain upgrade to nightly-2025-08-13 by @github-actions[bot] in #4297
* [Breaking Change] Fail if stub verified doesn't have a contract harness by @carolynzech in #4295
* Kani Book Documentation Improvements by @carolynzech in #4296
* Automatic toolchain upgrade to nightly-2025-08-14 by @github-actions[bot] in #4298
* Automatic toolchain upgrade to nightly-2025-08-15 by @github-actions[bot] in #4299
* Automatic toolchain upgrade to nightly-2025-08-16 by @github-actions[bot] in #4300
* Automatic cargo update to 2025-08-18 by @github-actions[bot] in #4302
* Upgrade Rust toolchain to 2025-08-18 by @tautschnig in #4304
* Automatic toolchain upgrade to nightly-2025-08-19 by @github-actions[bot] in #4307
* Bump tests/perf/s2n-quic from `c64faf9` to `ff81604` by @dependabot[bot] in #4306
* Automatic toolchain upgrade to nightly-2025-08-20 by @github-actions[bot] in #4309
* Share body cache between harnesses within a codegen unit by @AlexanderPortland in #4276
* Add loop-contracts support for `for` loop by @thanhnguyen-aws in #4143
* RFC: Partitioned proofs by @AlexanderPortland in #4228
* Update toolchain to 08-25-2025 by @thanhnguyen-aws in #4316
* Automatic cargo update to 2025-08-25 by @github-actions[bot] in #4315
* Automatic toolchain upgrade to nightly-2025-08-26 by @github-actions[bot] in #4317
* Bump tests/perf/s2n-quic from `ff81604` to `fa30e8a` by @dependabot[bot] in #4318
* Automatic toolchain upgrade to nightly-2025-08-27 by @github-actions[bot] in #4319
* Handle const generics in stubbing code by @zhassan-aws in #4323
* Automatic toolchain upgrade to nightly-2025-08-28 by @github-actions[bot] in #4324
* Automatic toolchain upgrade to nightly-2025-08-29 by @github-actions[bot] in #4325
* Add import select_autoescape by @zhassan-aws in #4327
* Bump tracing-subscriber from 0.3.19 to 0.3.20 by @dependabot[bot] in #4328
* Bump ncipollo/release-action from 1.18.0 to 1.19.1 by @dependabot[bot] in #4331
* Bump tests/perf/s2n-quic from `fa30e8a` to `d2c0794` by @dependabot[bot] in #4332
* Automatic cargo update to 2025-09-01 by @github-actions[bot] in #4330
* Upgrade toolchain to 2025-09-02 by @zhassan-aws in #4333
* Automatic toolchain upgrade to nightly-2025-09-03 by @github-actions[bot] in #4335
* Automatic toolchain upgrade to nightly-2025-09-04 by @github-actions[bot] in #4336
* Automatic toolchain upgrade to nightly-2025-09-05 by @github-actions[bot] in #4337
* Replace fxhash with rustc-hash by @zhassan-aws in #4341
* Fix LLBC regressions by @zhassan-aws in #4338
* Bump ncipollo/release-action from 1.19.1 to 1.20.0 by @dependabot[bot] in #4344
* Automatic cargo update to 2025-09-08 by @github-actions[bot] in #4342
* Bump tests/perf/s2n-quic from `d2c0794` to `26e2402` by @dependabot[bot] in #4346
* Automatic toolchain upgrade to nightly-2025-09-06 by @github-actions[bot] in #4339
* Combo of small performance changes by @AlexanderPortland in #4314
* Upgrade cargo_metadata dependency by @tautschnig in #4308
* Bump actions/github-script from 7 to 8 by @dependabot[bot] in #4343
* Bump actions/labeler from 5 to 6 by @dependabot[bot] in #4345
* Automatic toolchain upgrade to nightly-2025-09-07 by @github-actions[bot] in #4347
* Workaround sporadic git submodule failure by @tautschnig in #4349
* Implement BoundedArbitrary for boxed slices by @zhassan-aws in #4340
* Automatic toolchain upgrade to nightly-2025-09-08 by @github-actions[bot] in #4350
* Contain CI permissions to avoid global read-write by @tautschnig in #4348
* Automatic toolchain upgrade to nightly-2025-09-09 by @github-actions[bot] in #4352
* Upgrade Rust toolchain to 2025-09-10 by @tautschnig in #4354
* Automatic toolchain upgrade to nightly-2025-09-11 by @github-actions[bot] in #4355
* Automatic toolchain upgrade to nightly-2025-09-12 by @github-actions[bot] in #4356
* Do not run PR/issue-creating workflows in forks by @tautschnig in #4357
* Automatic toolchain upgrade to nightly-2025-09-13 by @github-actions[bot] in #4358
* Automatic toolchain upgrade to nightly-2025-09-14 by @github-actions[bot] in #4359
* Automatic toolchain upgrade to nightly-2025-09-15 by @github-actions[bot] in #4360
* Automatic cargo update to 2025-09-15 by @github-actions[bot] in #4361
* Bump tests/perf/s2n-quic from `26e2402` to `fc9b388` by @dependabot[bot] in #4362
* Automatic toolchain upgrade to nightly-2025-09-16 by @github-actions[bot] in #4363
* Automatic toolchain upgrade to nightly-2025-09-17 by @github-actions[bot] in #4364
* Upgrade Rust toolchain to 2025-09-18 by @tautschnig in #4366
* Autoharness: use SHA-1 to produce codegen unit file names by @tautschnig in #4370
* Upgrade Rust toolchain to 2025-09-19 by @tautschnig in #4369
* Automatic toolchain upgrade to nightly-2025-09-20 by @github-actions[bot] in #4371
* Automatic toolchain upgrade to nightly-2025-09-21 by @github-actions[bot] in #4372
* Update attributes.md by @0xsecaas in #4376
* Bump tests/perf/s2n-quic from `fc9b388` to `b131854` by @dependabot[bot] in #4377
* Automatic toolchain upgrade to nightly-2025-09-22 by @github-actions[bot] in #4373
* Automatic cargo update to 2025-09-22 by @github-actions[bot] in #4374
* Revert "Cache dependencies for CI jobs (#4181)" by @tautschnig in #4375
* Automatic toolchain upgrade to nightly-2025-09-23 by @github-actions[bot] in #4378
* Automatic toolchain upgrade to nightly-2025-09-24 by @github-actions[bot] in #4379
* Automatic toolchain upgrade to nightly-2025-09-25 by @github-actions[bot] in #4380
* Automatic toolchain upgrade to nightly-2025-09-26 by @github-actions[bot] in #4381
* Automatic toolchain upgrade to nightly-2025-09-27 by @github-actions[bot] in #4382
* Automatic toolchain upgrade to nightly-2025-09-28 by @github-actions[bot] in #4383
* Automatic toolchain upgrade to nightly-2025-09-29 by @github-actions[bot] in #4384
* Automatic cargo update to 2025-09-29 by @github-actions[bot] in #4385
* Bump tests/perf/s2n-quic from `b131854` to `1cca93b` by @dependabot[bot] in #4386
* Upgrade Rust toolchain to 2025-09-30 by @tautschnig in #4388
* Automatic toolchain upgrade to nightly-2025-10-01 by @github-actions[bot] in #4389
* Automatic toolchain upgrade to nightly-2025-10-02 by @github-actions[bot] in #4391
* Upgrade Rust toolchain to 2025-10-03 by @tautschnig in #4393
* Complete CI permissions limiting by @tautschnig in #4394
* Automatic toolchain upgrade to nightly-2025-10-04 by @github-actions[bot] in #4395
* Automatic toolchain upgrade to nightly-2025-10-05 by @github-actions[bot] in #4396
* Automatic cargo update to 2025-10-06 by @github-actions[bot] in #4398
* Automatic toolchain upgrade to nightly-2025-10-06 by @github-actions[bot] in #4397
* Automatic toolchain upgrade to nightly-2025-10-07 by @github-actions[bot] in #4401
* Automatic toolchain upgrade to nightly-2025-10-08 by @github-actions[bot] in #4402
* Automatic toolchain upgrade to nightly-2025-10-09 by @github-actions[bot] in #4403
* Automatic toolchain upgrade to nightly-2025-10-10 by @github-actions[bot] in #4404
* Automatic toolchain upgrade to nightly-2025-10-11 by @github-actions[bot] in #4405
* Bump tests/perf/s2n-quic from `1cca93b` to `995f37b` by @dependabot[bot] in #4400
* Automatic cargo update to 2025-10-13 by @github-actions[bot] in #4409
* Upgrade Rust toolchain to 2025-10-12 by @tautschnig in #4407
* Bump tests/perf/s2n-quic from `995f37b` to `5240fd6` by @dependabot[bot] in #4410
* Automatic toolchain upgrade to nightly-2025-10-13 by @github-actions[bot] in #4411
* Automatic toolchain upgrade to nightly-2025-10-14 by @github-actions[bot] in #4412
* Automatic toolchain upgrade to nightly-2025-10-15 by @github-actions[bot] in #4414
* Automatic toolchain upgrade to nightly-2025-10-16 by @github-actions[bot] in #4415
* Automatic toolchain upgrade to nightly-2025-10-17 by @github-actions[bot] in #4416
* Automatic cargo update to 2025-10-20 by @github-actions[bot] in #4417
* Automatic toolchain upgrade to nightly-2025-10-18 by @github-actions[bot] in #4418
* Bump tests/perf/s2n-quic from `5240fd6` to `73c9278` by @dependabot[bot] in #4419
* Automatic toolchain upgrade to nightly-2025-10-19 by @github-actions[bot] in #4420
* Automatic toolchain upgrade to nightly-2025-10-20 by @github-actions[bot] in #4421
* Automatic toolchain upgrade to nightly-2025-10-21 by @github-actions[bot] in #4422
* Automatic toolchain upgrade to nightly-2025-10-22 by @github-actions[bot] in #4423
* Automatic toolchain upgrade to nightly-2025-10-23 by @github-actions[bot] in #4424
* Automatic cargo update to 2025-10-27 by @github-actions[bot] in #4428
* Bump tests/perf/s2n-quic from `73c9278` to `42fe409` by @dependabot[bot] in #4429
* Bump actions/download-artifact from 5 to 6 by @dependabot[bot] in #4430
* Upgrade Rust toolchain to 2025-10-24 by @tautschnig in #4426
* Automatic toolchain upgrade to nightly-2025-10-25 by @github-actions[bot] in #4431
* Automatic toolchain upgrade to nightly-2025-10-26 by @github-actions[bot] in #4432
* Automatic toolchain upgrade to nightly-2025-10-27 by @github-actions[bot] in #4433
* Automatic toolchain upgrade to nightly-2025-10-28 by @github-actions[bot] in #4434
* Automatic toolchain upgrade to nightly-2025-10-29 by @github-actions[bot] in #4435
* Automatic toolchain upgrade to nightly-2025-10-30 by @github-actions[bot] in #4436
* Automatic toolchain upgrade to nightly-2025-10-31 by @github-actions[bot] in #4437
* Automatic cargo update to 2025-11-03 by @github-actions[bot] in #4441
* Upgrade Rust toolchain to 2025-11-03 by @tautschnig in #4440
* Bump tests/perf/s2n-quic from `42fe409` to `e726f08` by @dependabot[bot] in #4443
* Switch macos-13 CI jobs to macos-15-intel by @tautschnig in #4442
* Automatic toolchain upgrade to nightly-2025-11-04 by @github-actions[bot] in #4444
* Incrementally update charon submodule with LLBC backend adaptations by @tautschnig in #4445
* Automatic toolchain upgrade to nightly-2025-11-05 by @github-actions[bot] in #4446
* Major-version update cargo dependencies by @tautschnig in #4447

## New Contributors
* @0xsecaas made their first contribution in #4376

**Full Changelog**: kani-0.65.0...kani-0.66.0
```


By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 and MIT licenses.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants