Hi Benoit,

The problem here is that Why3 accepted a clone instruction which was,
strictly speaking, invalid, and gave it a meaning which made it valid, but
which was not the one you wanted. Here is what happened:
1. The type 'storage' declared in Afunction is immutable, because WhyML
operates under assumption "no hidden effects, no hidden state", and thus
everything is immutable unless explicitly declared otherwise. Any module
that uses Afunction (as an interface to a library) assumes that values of
type 'storage' do not change.
2. Module Test declares a mutable type 'storage' but then clones Afunction
and instantiates Afunction's immutable type 'storage' with this mutable
type. Why3 should have refused this instantiation but didn't [bug 1]. What
it did instead is it instantiated Afunction's immutable type 'storage' with
the _snapshot_ type '{storage}' (note the curly braces). Snapshot types
serve to represent momentary states of mutable values and as such they are
immutable.
3. As a consequence of this, the cloned function 'exec' now has type
'{storage} -> init'. This should have led to typing error at the function
'update': a mutable value cannot be passed directly to a function expecting
a snapshot, and thus the type of 's' was inferred to be '{storage}', which
should have conflicted with the type annotation 'storage' [bug 2]. The
code, however, was rejected, when it tried to write into 's', since 's',
internally, was considered immutable.

The correct way of doing what you wanted is to declare the type 'storage'
in Afunction as mutable : 'type storage = abstract mutable { }'. (By the
way, simply writing 'type storage' is equivalent to 'type storage =
abstract { }'.)

As for us, we have two bugs to fix:
bug 1: Immutable types shouldn't be allowed to be instantiated by mutable
types.
bug 2: Explicit type annotations without curly braces should not be
resolvable as snapshots.

Thanks for the report!

Best,
Andrei



On Mon, 29 Apr 2019 at 22:31, Benoit Rognier <benoit.rogn...@edukera.com>
wrote:

> Hello, Why3-club,
>
> The following code
>
> theory Afunction
>   use int.Int
>
>   type storage
>
>   val function exec storage : int
>
> end
>
> theory Test
>   use int.Int
>   use Afunction
>
>   type storage = {
>        mutable a : int;
>   }
>
>   clone Afunction as Af with type storage = storage
>
>   let update (s : storage) = s.a <- Af.exec s
>
> end
>
> generates the following compilation error :
>
> line 24, characters 1-17: This assignment modifies a value of the
> immutable type {storage}
>
> What does it mean ? and why is the type 'storage' considered to be
> immutable ?
> Thank you,
> Benoit Rognier
> _______________________________________________
> Why3-club mailing list
> Why3-club@lists.gforge.inria.fr
> https://lists.gforge.inria.fr/mailman/listinfo/why3-club
>
_______________________________________________
Why3-club mailing list
Why3-club@lists.gforge.inria.fr
https://lists.gforge.inria.fr/mailman/listinfo/why3-club

Reply via email to