Skip to content

missing vstd specification for executable str equality #2765

Description

@wood-ghost

There seems to be a missing specification connecting executable str equality with equality of Seq<char> .

The following example fails to verify:

equality with ==

use vstd::prelude::*;

verus! {

struct TextSource;

uninterp spec fn modeled_text(source: &TextSource) -> Seq<char>;

#[verifier::external_body]
fn get_text<'a>(source: &'a TextSource) -> (result: &'a str)
    ensures
        result@ == modeled_text(source),
{
    "hello world"
}

spec fn is_hello(source: &TextSource) -> bool {
    modeled_text(source) == "hello world"@
}

fn check(source: &TextSource) -> (result: bool)
    ensures
        result == is_hello(source),
{
    get_text(source) == "hello world"
}

}

The postcondition of check cannot be proved, even though get_text guarantees result@ == modeled_text(source) and the executable comparison is get_text(source) == "hello world"

Workaround

Currently it works by rewriting the original codes using a helper function

#[verifier::external_body]
fn str_equal(a: &str, b: &str) -> (result: bool)
    ensures
        result == (a@ == b@),
{
    a == b
}

and replace the check body with

str_equal(get_text(source), "hello world")

Complete working version:

use vstd::prelude::*;

verus! {

struct TextSource;

uninterp spec fn modeled_text(source: &TextSource) -> Seq<char>;

#[verifier::external_body]
fn get_text<'a>(source: &'a TextSource) -> (result: &'a str)
    ensures
        result@ == modeled_text(source),
{
    "hello world"
}

#[verifier::external_body]
fn str_equal(a: &str, b: &str) -> (result: bool)
    ensures
        result == (a@ == b@),
{
    a == b
}

spec fn is_hello(source: &TextSource) -> bool {
    modeled_text(source) == "hello world"@
}

fn check(source: &TextSource) -> (result: bool)
    ensures
        result == is_hello(source),
{
    str_equal(get_text(source), "hello world")
}

}

Expected behavior

The first version should verify without requiring a trusted helper.

The Playground share interface appears to preserve only one version at a time, so I included only the failing version as a Playground link and included the working workaround inline.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions