Skip to content

Unsolicited state transition #51

@rodrigomilisse

Description

@rodrigomilisse

When analising a StateRefinement without a to value, the from value may replace the current information about the state variable used in the from value.

Example

import liquidjava.specification.*;
import java.util.ArrayList;

@ExternalRefinementsFor("java.util.ArrayList")
@Ghost("int x")
public interface TestTransitionsRefinements<E> {
	@StateRefinement(to = "x(this) == 0")
	public abstract void ArrayList();

	@StateRefinement(to = "x(this) == x(old(this)) + 1")
	public abstract void add(E e);

	@StateRefinement(from = "x(this) > 0")
	public abstract E get(int index);

	@StateRefinement(from = "x(this) > 1")
	public abstract E getFirst();

	@StateRefinement(from = "x(this) > 0", to = "x(this) == x(old(this)) - 1")
	public abstract void remove(int index);
}

public class TestTransitions {

	public static void main(String[] args) {
		ArrayList<Integer> list = new ArrayList<>();
		list.add(1);
		list.add(2);

		list.remove(0);
		list.remove(0);

		// ok

		ArrayList<Integer> list2 = new ArrayList<>();
		list2.add(1);
		list2.add(2);
		list2.getFirst();
		list2.remove(0);
		list2.remove(0);

		// ok

		ArrayList<Integer> list3 = new ArrayList<>();
		list3.add(1);
		list3.add(2);
		list3.get(0);
		list3.remove(0);
		list3.remove(0);

		// fail
	}
}

In this case, the detail x(this) == 2 is replaced by x(this) > 0 when calling the get() method. This loss of information means that an error is thrown when trying to call remove() twice because the second remove can no longer guarantee it's pre-condition that x(this) > 0. The first list doen't call a method before the removes, so the information is kept and the second list calls getFirst() with a stronger pre-condition that ensures that at least two calls to remove are possible.

Error Thrown

______________________________________________________
Failed to check state transitions when calling list3.remove(0) in:

list3.remove(0)

Expected possible states:(x(this) > 0)

State found:
----------------------------------------------------------------------------------------------------------------------------------
∀#list3_43:ArrayList, (x(#list3_43) == x(#list3_41) - 1)  => 
∀#list3_41:ArrayList, (x(#list3_41) > 0) 
----------------------------------------------------------------------------------------------------------------------------------

Instance translation table:
----------------------------------------------------------------------------------------------------------------------------------
| Variable Name                    | Created in                                                   | File 
----------------------------------------------------------------------------------------------------------------------------------
| #list3_41                        | list3.get(0)                                                 | TestTransitions.java:47, 3 
| #list3_43                        | list3.remove(0)                                              | TestTransitions.java:48, 3 
----------------------------------------------------------------------------------------------------------------------------------

Location: (/home/rodri/documents/LASIGE/barista/saved/new/TestTransitions.java:49)
______________________________________________________

In summary x(this) == x(old(this)) - 1 && x(old(this)) > 0 instead of x(this) == x(old(this)) - 1 && x(old(this)) == 2

Intended behaviour

StateRefinements without a to value should not affect state

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions