Skip to content

Ghost variable not properly handled in loopΒ #3720

@FliegendeWurst

Description

@FliegendeWurst

Description

When using a ghost variable in a loop, KeY assumes it will always have the initial value (value before the loop is executed).

Reproducible

always

Steps to reproduce

File SetGhost.java:

import java.util.List;

public class SetGhost {
    /*@ public normal_behavior
      @ requires \invariant_for(l);
      @ ensures \result == l.seq.length;
      @*/
    static int counter(List l) {
        int listSize = l.size();
        int counter = 0;
        //@ ghost int iter;
        //@ set iter = 0;
        
        /*@ loop_invariant
          @ i >= 0 && i <= listSize && listSize == l.size()
          @  && i == counter
          @  && iter == counter
          @ ;
          @ decreases listSize - i;
          @ assignable counter,iter;
          @*/
        for (int i = 0; i < listSize; i++) {
            counter++;
            //@ set iter = iter + 1;
            //@ assert iter == 1;
            assert counter == 1;
        }
        //@ assert iter == counter;
        return counter;
    }
}
  1. Load SetGhost.java
  2. Run automode

Expected behavior: the proof does not close, both assertions fail to prove
Actual behavior: proof closes

Reproducer using `\seq` instead of int

In this case, the assertion's validity can be proven, but the loop invariant fails to prove (since KeY thinks values == [l.get(i)] with unknown i).

import java.util.List;

public class SetGhostSeq {
    /*@ public normal_behavior
      @ requires \invariant_for(l);
      @ ensures \result == l.seq.length;
      @*/
    static int counter(List l) {
        int listSize = l.size();
        int counter = 0;
        //@ ghost \seq values;
        //@ set values = \seq_empty;
        
        /*@ loop_invariant
          @ i >= 0 && i <= listSize && listSize == l.size()
          @  && values == l.seq[0 .. values.length]
          @  && i == counter
          @  && \invariant_for(l)
          @ ;
          @ decreases listSize - i;
          @ assignable counter,values;
          @*/
        for (int i = 0; i < listSize; i++) {
            // System.out.println("" + counter);
            counter++;
            Object x = l.get(i);
            //@ set values = \seq_concat(values, \seq_singleton(x));
            //@ assert values.length == 1;
        }
        return counter;
    }
}

Additional information


cc @WolframPfeifer

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions