ocaml-gospel / ortac

Runtime assertion checking based on Gospel specifications
https://ocaml-gospel.github.io/ortac/
MIT License
36 stars 10 forks source link

Ortac swaps the type `unit` and the value `()` #207

Closed Lucccyo closed 4 months ago

Lucccyo commented 5 months ago

Modeling a type with unit and testing it with Ortac produces a code that swaps around the type unit and the value ().

type t
(*@ model t: unit *)

() at line 7 should be unit, and unit at line 12 should be ().

1 open Lwt_op
2 module Spec =
3   struct
4     open STM
5     [...]
6     type nonrec state = {
7       t_1: () }
8     let init_state =
9       let u = () in
10      {
11        t_1 =
12          (try unit
13           with
14           | e ->
15               raise [...]
16      }
17    [...]
n-osborne commented 5 months ago

Thank you! This is indeed a couple of problems.

I believe the first problem originates from the fact that unit is encoded in Gospel as a tuple of length 0. It may be the condition in Ortac_core.Ocaml_of_gospel.core_type_of_ty_with_subst line 232 that is too weak.

Regarding the second problem, it may come from Gospel itself. As we can see in the following example, Gospel gives the name unit to the value (), then when translating the Tterm.Tapp, ortac will look and uses the ls_name.

$ cat > foo.mli << EOF
> val f : int -> int
> (*@ y = f x
>     modifies () *)
> EOF
$ gospel dumpast foo.mli | awk "/sp_wr/,/sp_cs/"
                 sp_wr =
                 [{ Tterm.t_node =
                    (Tterm.Tapp (
                       { Symbols.ls_name = unit; ls_args = [];
                         ls_value =
                         (Some { Ttypes.ty_node =
                                 (Ttypes.Tyapp (
                                    { Ttypes.ts_ident = unit_1; ts_args = [];
                                      ts_alias = None },
                                    []))
                                 });
                         ls_constr = true; ls_field = false },
                       []));
                    t_ty =
                    (Some { Ttypes.ty_node =
                            (Ttypes.Tyapp (
                               { Ttypes.ts_ident = unit_1; ts_args = [];
                                 ts_alias = None },
                               []))
                            });
                    t_attrs = []; t_loc = /tmp/bob.mli:3:13 }
                   ];
                 sp_cs = []; sp_diverge = false; sp_pure = false;