verus-lang / verus

Verified Rust for low-level systems code

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Panics with `assert(..) by (compute)`

matthias-brun opened this issue · comments

These two files both cause panics.

use vstd::prelude::*;

verus!{

fn main() { }

global size_of usize == 8;

pub open spec fn foo() -> int {
    if 10 == 1 {
        1
    } else {
        let w = 10 as u64;
        let lz = w.leading_zeros();
        (w >> lz as u64) as int
    }
}

pub proof fn bar() {
    assert(foo() == 0) by (compute);
    // Doesn't panic:
    // assert(foo() == 0) by (compute_only);
}

}
ξ verus-release /st/verus/test2.rs
thread '<unnamed>' panicked at vir/src/sst_to_air.rs:1203:67:
bounded integer type
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' panicked at rust_verify/src/verifier.rs:1837:29:
worker thread panicked
use vstd::prelude::*;

verus!{

fn main() { }

// This line makes Verus not panic
// global size_of usize == 8;

spec fn foo(size: int) -> int {
    let bits = usize::BITS as int;
    if bits == 1 {
        0
    } else if bits <= 8 {
        0
    } else {
        0
    }
}

proof fn bar() {
    assert(foo(0) == 0) by (compute);
    // Doesn't panic:
    // assert(foo() == 0) by (compute_only);
}

}
ξ verus-release /st/verus/test.rs
thread '<unnamed>' panicked at rust_verify/src/verifier.rs:715:21:
internal error: generated ill-typed AIR code: error 'error 'use of undeclared variable bits~17$' in expression 'bits~17$'' in expression '(<= bits~17$ 8)'
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' panicked at rust_verify/src/verifier.rs:332:17:
dropped, expected call to `into_inner` instead
stack backtrace:
   0:     0x7f6bdd51349c - std::backtrace_rs::backtrace::libunwind::trace::he43a6a3949163f8c
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:     0x7f6bdd51349c - std::backtrace_rs::backtrace::trace_unsynchronized::h50db52ca99f692e7
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
[...]

When I try the first file, it errors with:

error: cannot call function with mode exec
  --> issue-928a.rs:14:18
   |
14 |         let lz = w.leading_zeros();
   |                  ^^^^^^^^^^^^^^^^^

probably because we recently removed the when_used_as_spec annotation. If I manually apply the corresponding spec function let lz = vstd::std_specs::bits::u64_leading_zeros(w);, I do see a similar panic:

thread '<unnamed>' panicked at vir/src/sst_to_air.rs:1204:44:
expected bounded integer type Int(Nat)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' panicked at rust_verify/src/verifier.rs:1837:29:
worker thread panicked

To eliminate anything that might be related to #944, I simplified it further to:

use vstd::prelude::*;

verus!{

fn main() { }

pub open spec fn id(x:int) -> int;

pub proof fn bar() {
    assert(
        { (10 as u64 >> (id(5) as u64)) as int }
        == 0) by (compute);
}

}

It looks like the problem was that the 10 as 64 was getting treated as a clip operation, which when the value is actually in bounds, simply clones the inner expression. In this case, the 10 has type int, which then leads the bit-vector-related sanity checks to complain.

For the second program, we can simplify foo a bit:

spec fn foo(size: int) -> int {
    let bits = usize::BITS as int;
    if bits == 1 {
        0
    } else {
        bits 
    }
}

The issue is that when global size_of usize is not set, we can't simplify the conditional in if statement beyond substituting in the value of bits, and hence we stop simplifying (since we know that we won't be able to execute one of the two branches). However, that means that the reference to bits in the false branch is left as a dangling reference when we try to hand things off to Z3.