qcheck icon indicating copy to clipboard operation
qcheck copied to clipboard

ppx_deriving_qcheck cannot derive a generator from a recursive type declaration with containers

Open Invizory opened this issue 3 years ago • 5 comments

Minimal reproducible example:

type t = Box of t list [@@deriving qcheck]

ppx_deriving_qcheck produces the following generator with unbound gen:

let gen = QCheck.Gen.map (fun gen0 -> Box gen0) (QCheck.Gen.list gen)

This trick (given -rectypes is enabled) make it derive the following generator:

type 'a open_t = Box of 'a list
and t = t open_t
[@@deriving qcheck]
let rec gen_open_t gen_a =
  QCheck.Gen.map (fun gen0 -> Box gen0) (QCheck.Gen.list gen_a)
and gen_sized n = gen_open_t (gen_sized (n / 2))
let gen = QCheck.Gen.sized gen_sized

However, this generatior is non-terminating.

Invizory avatar Jan 08 '23 14:01 Invizory

Thanks for the report!

Ping @vch9 - I think we are not handling type constructors correctly in is_rec_typ

jmid avatar Jan 08 '23 17:01 jmid

Thanks for the report again.

Definitely a problem in is_rec_type, t should not be considered recursive (in the latter). I will try to have a look

vch9 avatar Jan 09 '23 09:01 vch9

I think the deriver fails on a very much simpler example: type t = t list. I did not consider the rectypes flag as I just discovered it :sweat_smile:.

It creates:

let gen = QCheck.Gen.list gen
let arb = QCheck.make @@ gen

Should we be smarter than:

let rec gen = QCheck.Gen.list gen
let arb = QCheck.make @@ gen

?

vch9 avatar Jan 09 '23 10:01 vch9

IMO using rectypes is a cornercase that we don't necessarily have to support (I read the report as trying to use it as a workaround).

I suggest prioritising the reported case type t = Box of t list of "vanilla OCaml usage" where it seems we don't identify an occurrence of t as recursive when it is a type parameter to a type constructor such as list (or option or result ...) :thinking:

In trying out a potential workaround I just experienced the following error variant:

utop # #require "ppx_deriving";;
utop # #require "ppx_deriving_qcheck";;
utop # type t = Box of foo
       and foo = t list [@@deriving qcheck];;
Error: Unbound value n

jmid avatar Jan 09 '23 11:01 jmid