verus-lang / verus

Verified Rust for low-level systems code
MIT License
1.15k stars 66 forks source link

Chained conjunction forces spec mode #1149

Closed jonhnet closed 3 months ago

jonhnet commented 4 months ago

Run this with verus:

use builtin_macros::verus;

verus!{
    exec fn foo(a: usize, b: usize, c: usize) -> usize {
        if a <= b <= c { 1 } else { 2 }
    }
}

You'll get error: condition must have mode exec, which is quite confusing.

A workaround is to replace the condition with a <= b && b <= c, so evidently operator chaining causes the expression to suddenly become a spec expression.

Is there any reason we shouldn't allow chained expressions in exec text and desugar them to a collection of conjuncts?

tjhance commented 4 months ago

Definitely a confusing error message that should be fixed.

I'm not really sure about supporting chained inequalities in exec code though. I think generally it's a good idea to leave exec code as 'normal rust' as much as possible.

jonhnet commented 4 months ago

I think generally it's a good idea to leave exec code as 'normal rust' as much as possible.

While I acknowledge your point, I'd like to also remind us that verus! is a language design problem (opportunity!), and we should be willing to design the language. Chained inequalities don't have a special meaning in spec land, so it's weird that they shouldn't work in either context. I can't see an upside to excluding them other than "now you can't copy-paste exec code into a non-verus! context and have it work without editing", but I'm not very excited about retaining that property at the expense of making the verus! language less usable.

jaybosamiya commented 4 months ago

Given that Rust hasn't had chained comparison in a while (relevant thread that started in 2017: https://github.com/rust-lang/rfcs/issues/2083), and our semantics of chained comparison (e.g., a < b < c == a < b && b < c) seems to be the only possibly reasonable one, and that rustc currently complains with the correct fix on chained comparisons (example below), overall I think us supporting exec-mode chained comparisons would not be too bad.

((Click here for current rustc error message)) ```console $ rustc x.rs error: comparison operators cannot be chained --> x.rs:2:8 | 2 | if 1 < 2 < 3 { | ^ ^ | help: split the comparison into two | 2 | if 1 < 2 && 2 < 3 { | ++++ error: aborting due to 1 previous error ```

Important things to keep in mind (esp in exec-mode), if we decide to include this: