Skip to content

Quantifiers assume that ranges are always usizes #4135

@carolynzech

Description

@carolynzech

This is a tracking issue for fixing the known quantifiers limitation that the ranges must be usizes.

I tried this code:

#[kani::requires(min != 0 && max != 0)]
#[kani::ensures(|result| *result != 0 && max % *result == 0 && min % *result == 0)]
#[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX)| !(max % i == 0 && min % i == 0) || *result >= i))]
#[kani::recursion]
fn gcd(mut max: u8, mut min: u8) -> u8 {
    if min > max {
        std::mem::swap(&mut max, &mut min);
    }

    let rest = max % min;
    if rest == 0 { min } else { gcd(max, rest) }
}

#[kani::proof_for_contract(gcd)]
fn check_gcd() {
    let max: u8 = kani::any();
    let min: u8 = kani::any();
    gcd(max, min);
}

using the following command line invocation:

cargo kani -Z function-contracts

with Kani version: 0.62.0

I expected to see this happen: verification success

Instead, this happened:

cmzech@80a9971b5e20 playground % cargo kani -Z function-contracts
Kani Rust Verifier 0.62.0 (cargo plugin)
   Compiling playground v0.1.0 (/Users/cmzech/playground)
error[E0308]: mismatched types
 --> src/lib.rs:3:49
  |
3 | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX)| !(max % i == 0 && min % i == 0) || *result >= i))]
  |                          -----------------------^^^^^^^---------------------------------------------------
  |                          |                      |
  |                          |                      expected `usize`, found `u8`
  |                          expected due to this
  |
help: you can convert a `u8` to a `usize`
  |
3 | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX.into())| !(max % i == 0 && min % i == 0) || *result >= i))]
  |                                                        +++++++

error[E0631]: type mismatch in closure arguments
  --> src/lib.rs:3:26
   |
3  | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX)| !(max % i == 0 && min % i == 0) || *result >= i))]
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                          |
   |                          expected due to this
   |                          found signature defined here
   |                          required by a bound introduced by this call
   |
   = note: expected closure signature `fn(usize) -> _`
              found closure signature `fn(u8) -> _`
note: required by a bound in `kani::internal::kani_forall`
  --> /Users/cmzech/kani/library/kani/src/lib.rs:55:1
   |
55 | kani_core::kani_lib!(kani);
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
   | |
   | required by a bound in this function
   | required by this bound in `kani_forall`
   = note: this error originates in the macro `kani::forall` which comes from the expansion of the macro `kani_core::kani_lib` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider wrapping the function in a closure
  --> /Users/cmzech/kani/library/kani_core/src/lib.rs:203:71
   |
203|                 kani::internal::kani_forall(lower_bound, upper_bound, |arg0: usize| predicate(/* u8 */))
   |                                                                       +++++++++++++          ++++++++++

error[E0308]: mismatched types
 --> src/lib.rs:3:49
  |
3 | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX)| !(max % i == 0 && min % i == 0) || *result >= i))]
  |                          -----------------------^^^^^^^---------------------------------------------------
  |                          |                      |
  |                          |                      expected `usize`, found `u8`
  |                          expected due to this
  |
help: you can convert a `u8` to a `usize`
  |
3 | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX.into())| !(max % i == 0 && min % i == 0) || *result >= i))]
  |                                                        +++++++

error[E0631]: type mismatch in closure arguments
  --> src/lib.rs:3:26
   |
3  | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX)| !(max % i == 0 && min % i == 0) || *result >= i))]
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                          |
   |                          expected due to this
   |                          found signature defined here
   |                          required by a bound introduced by this call
   |
   = note: expected closure signature `fn(usize) -> _`
              found closure signature `fn(u8) -> _`
note: required by a bound in `kani::internal::kani_forall`
  --> /Users/cmzech/kani/library/kani/src/lib.rs:55:1
   |
55 | kani_core::kani_lib!(kani);
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
   | |
   | required by a bound in this function
   | required by this bound in `kani_forall`
   = note: this error originates in the macro `kani::forall` which comes from the expansion of the macro `kani_core::kani_lib` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider wrapping the function in a closure
  --> /Users/cmzech/kani/library/kani_core/src/lib.rs:203:71
   |
203|                 kani::internal::kani_forall(lower_bound, upper_bound, |arg0: usize| predicate(/* u8 */))
   |                                                                       +++++++++++++          ++++++++++

error[E0308]: mismatched types
 --> src/lib.rs:3:49
  |
3 | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX)| !(max % i == 0 && min % i == 0) || *result >= i))]
  |                          -----------------------^^^^^^^---------------------------------------------------
  |                          |                      |
  |                          |                      expected `usize`, found `u8`
  |                          expected due to this
  |
help: you can convert a `u8` to a `usize`
  |
3 | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX.into())| !(max % i == 0 && min % i == 0) || *result >= i))]
  |                                                        +++++++

error[E0631]: type mismatch in closure arguments
  --> src/lib.rs:3:26
   |
3  | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX)| !(max % i == 0 && min % i == 0) || *result >= i))]
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                          |
   |                          expected due to this
   |                          found signature defined here
   |                          required by a bound introduced by this call
   |
   = note: expected closure signature `fn(usize) -> _`
              found closure signature `fn(u8) -> _`
note: required by a bound in `kani::internal::kani_forall`
  --> /Users/cmzech/kani/library/kani/src/lib.rs:55:1
   |
55 | kani_core::kani_lib!(kani);
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
   | |
   | required by a bound in this function
   | required by this bound in `kani_forall`
   = note: this error originates in the macro `kani::forall` which comes from the expansion of the macro `kani_core::kani_lib` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider wrapping the function in a closure
  --> /Users/cmzech/kani/library/kani_core/src/lib.rs:203:71
   |
203|                 kani::internal::kani_forall(lower_bound, upper_bound, |arg0: usize| predicate(/* u8 */))
   |                                                                       +++++++++++++          ++++++++++

error[E0308]: mismatched types
 --> src/lib.rs:3:49
  |
3 | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX)| !(max % i == 0 && min % i == 0) || *result >= i))]
  |                          -----------------------^^^^^^^---------------------------------------------------
  |                          |                      |
  |                          |                      expected `usize`, found `u8`
  |                          expected due to this
  |
help: you can convert a `u8` to a `usize`
  |
3 | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX.into())| !(max % i == 0 && min % i == 0) || *result >= i))]
  |                                                        +++++++

error[E0631]: type mismatch in closure arguments
  --> src/lib.rs:3:26
   |
3  | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX)| !(max % i == 0 && min % i == 0) || *result >= i))]
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                          |
   |                          expected due to this
   |                          found signature defined here
   |                          required by a bound introduced by this call
   |
   = note: expected closure signature `fn(usize) -> _`
              found closure signature `fn(u8) -> _`
note: required by a bound in `kani::internal::kani_forall`
  --> /Users/cmzech/kani/library/kani/src/lib.rs:55:1
   |
55 | kani_core::kani_lib!(kani);
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
   | |
   | required by a bound in this function
   | required by this bound in `kani_forall`
   = note: this error originates in the macro `kani::forall` which comes from the expansion of the macro `kani_core::kani_lib` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider wrapping the function in a closure
  --> /Users/cmzech/kani/library/kani_core/src/lib.rs:203:71
   |
203|                 kani::internal::kani_forall(lower_bound, upper_bound, |arg0: usize| predicate(/* u8 */))
   |                                                                       +++++++++++++          ++++++++++

error[E0308]: mismatched types
 --> src/lib.rs:3:49
  |
3 | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX)| !(max % i == 0 && min % i == 0) || *result >= i))]
  |                          -----------------------^^^^^^^---------------------------------------------------
  |                          |                      |
  |                          |                      expected `usize`, found `u8`
  |                          expected due to this
  |
help: you can convert a `u8` to a `usize`
  |
3 | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX.into())| !(max % i == 0 && min % i == 0) || *result >= i))]
  |                                                        +++++++

error[E0631]: type mismatch in closure arguments
  --> src/lib.rs:3:26
   |
3  | #[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX)| !(max % i == 0 && min % i == 0) || *result >= i))]
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                          |
   |                          expected due to this
   |                          found signature defined here
   |                          required by a bound introduced by this call
   |
   = note: expected closure signature `fn(usize) -> _`
              found closure signature `fn(u8) -> _`
note: required by a bound in `kani::internal::kani_forall`
  --> /Users/cmzech/kani/library/kani/src/lib.rs:55:1
   |
55 | kani_core::kani_lib!(kani);
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
   | |
   | required by a bound in this function
   | required by this bound in `kani_forall`
   = note: this error originates in the macro `kani::forall` which comes from the expansion of the macro `kani_core::kani_lib` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider wrapping the function in a closure
  --> /Users/cmzech/kani/library/kani_core/src/lib.rs:203:71
   |
203|                 kani::internal::kani_forall(lower_bound, upper_bound, |arg0: usize| predicate(/* u8 */))
   |                                                                       +++++++++++++          ++++++++++

Some errors have detailed explanations: E0308, E0631.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `playground` (lib) due to 10 previous errors
error: Failed to execute cargo (exit status: 101). Found 10 compilation errors.

I had to change the quantifier to this:

#[kani::ensures(|result| kani::forall!(|i in (1,u8::MAX as usize)| !(max as usize % (i as usize) == 0 && min as usize % (i as usize) == 0) || (*result as usize) >= (i as usize)))]

This is quite cumbersome. The error message is very confusing (and repetitive), so short of fixing the problem, we can at least try to improve that.

Metadata

Metadata

Labels

Z-QuantifiersIssues related to quantifiers[C] BugThis is a bug. Something isn't working.

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions