Skip to content

Non-null assumptions from predicates unfolding predicates inside functions #112

Open
@viper-admin

Description

@viper-admin

Created by @mschwerhoff on 2014-08-19 19:06
Last updated on 2015-01-23 07:07

Consider the following code:

#!text

field f: Int

predicate FF(x: Ref, y: Ref) {
  acc(x.f) && acc(y.f)
}

function fun4(x: Ref, y: Ref): Int
  requires acc(FF(x, y))
{ unfolding acc(FF(x, y)) in x.f }

method test7(x: Ref, y: Ref)
  requires acc(FF(x, y)) && fun4(x, y) == 1
{
  assert x != null // holds
  assert y != null // fails
}

When axiomatising functions such as fun4, Silicon includes the assumption that all receivers of field dereferences that occur inside function bodies are non-null (which is justified by the corresponding accessibility predicate). For fun4, for example, it would generate an axiom that (simplified) says forall x, y :: fun4(x, y) = ... && x != null.

Silicon does not add such an assumption for receivers which are used in accessibility predicates inside predicates which are unfolded inside functions, but whose corresponding locations are not actually dereferenced in the body. The receiver y used in acc(y.f) in predicate FF(x, y) above is an example of this.

It is not clear, however, how deep one should go in order to find receivers that cannot be null. For example, what if FF contains another (non-recursive) predicate P(...) - should it be inspected as well? Or only if FF contains an unfolding acc(P(...))?

In my opinion the current level of looking for receivers that cannot be null - that is, only looking at which fields are dereferenced in the function body - is reasonably intuitive; after all, when applying a function we (in general) only get to reason about the function definition one level down.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions