无法断言合同中的通配符权限

Cannot assert wildcard permission that was in contract

以下程序验证失败:

field f: Int

method m(g: Ref, i: Int)
requires acc(g.f, i * wildcard)
{
    assert acc(g.f, i * wildcard)
}

我第一次偶然发现 i 是一个更复杂的表达式(具体来说,是一个抽象函数)。当您将 i 变成常量时,它会进行验证。 Carbon 报告 https://github.com/viperproject/carbon/issues/376 中报告的错误。我以前可能曾经报告过此错误的根本原因,但我不确定,所以我想我会提出一个问题。这有可能是一个错误,还是(预期的)不完整?

将“i > 0”添加为 requires 子句会导致示例验证,我不太明白。如果我需要大于 0,或者没有“i > 0”子句的传递,我会期待一个格式正确的错误...?

有趣的例子!观察到的行为可能令人惊讶,但可以解释。在我们进入细节之前,先了解一些背景知识:当吸入可访问性谓词 acc(R, P) 时,对于某些资源 R 和权限表达式 p,则假设 none ≤ p。包含 none 是因为对 R 的许可可能是有条件的,例如requires p == (b ? write : none).

在您的示例中,这会产生 none ≤ i * k1,其中 k1 代表第一个通配符。对于后者,假定 none < k1 < write。观察 i == 0 是可能的,在这种情况下 i * k1 将是 none.

对于assert,引入了第二个通配符k2。在可以假设 k2 是“小于当前持有的任何读取分数”之前,即在可以假设 none < k2 < perm(g.f) 之前,必须检查 none < perm(g.f)。然而,这失败了:perm(g.f) is none if i == 0.