Skip to content

Commit cab908d

Browse files
authored
Merge pull request #272 from jmid/is_rec_typ_deriver_bug
Fix is_rec_typ deriver bug(s)
2 parents 46fcbfb + d779d26 commit cab908d

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
`Test.check_exn` honor test polarity by raising
77
`Test_unexpected_success` when a negative test (expected to have a
88
counter example), unexpectedly succeeds.
9+
- fix issue with `ppx_deriving_qcheck` deriving a generator with unbound
10+
`gen` for recursive types [#269](https://github.com/c-cube/qcheck/issues/269)
11+
and a related issue when deriving a generator for a record type
912
- ...
1013

1114
## 0.20

src/ppx_deriving_qcheck/ppx_deriving_qcheck.ml

+4-3
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,9 @@ let rec longident_to_str = function
111111
Printf.sprintf "%s %s" (longident_to_str lg1) (longident_to_str lg2)
112112

113113
let rec is_rec_typ env = function
114-
| { ptyp_desc = Ptyp_constr ({ txt = x; _ }, _); _ } ->
115-
List.exists (fun typ_name -> longident_to_str x = typ_name) env.Env.curr_types
114+
| { ptyp_desc = Ptyp_constr ({ txt = x; _ }, args); _ } ->
115+
List.exists (fun typ_name -> longident_to_str x = typ_name) env.Env.curr_types ||
116+
List.exists (is_rec_typ env) args
116117
| { ptyp_desc = Ptyp_tuple xs; _ } -> List.exists (is_rec_typ env) xs
117118
| { ptyp_desc = Ptyp_variant (rws, _, _); _ } ->
118119
List.exists (is_rec_row_field env) rws
@@ -128,7 +129,7 @@ and is_rec_row_field env rw =
128129
let is_rec_constr_decl env cd =
129130
match cd.pcd_args with
130131
| Pcstr_tuple cts -> List.exists (is_rec_typ env) cts
131-
| _ -> false
132+
| Pcstr_record ldcls -> List.exists (fun ldcl -> is_rec_typ env ldcl.pld_type) ldcls
132133

133134
(** [is_rec_type_decl env typ] looks for elements of [env.curr_types]
134135
recursively in [typ]. *)

test/ppx_deriving_qcheck/deriver/qcheck/test_textual.ml

+43
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,41 @@ let test_unused_variable () =
860860
in
861861
check_eq ~expected ~actual "deriving variant with unused fuel parameter"
862862

863+
(* Regression test: https://github.com/c-cube/qcheck/issues/269 *)
864+
let test_faulty_is_rec_typ_in_variant () =
865+
let expected =
866+
[
867+
[%stri let rec gen_sized n =
868+
QCheck.Gen.map (fun gen0 -> Foo gen0) (QCheck.Gen.list (gen_sized (n / 2)))];
869+
[%stri let gen = QCheck.Gen.sized gen_sized];
870+
[%stri let arb_sized n = QCheck.make @@ (gen_sized n)];
871+
[%stri let arb = QCheck.make @@ gen];
872+
]
873+
in
874+
let actual = f @@ extract [%stri type t = Foo of t list]
875+
in
876+
check_eq ~expected ~actual "deriving rec type in a type constructor inside variant"
877+
878+
let test_faulty_is_rec_constr_decl () =
879+
let expected =
880+
[
881+
[%stri let rec gen_sized n =
882+
match n with
883+
| 0 -> QCheck.Gen.pure Foo
884+
| _ ->
885+
QCheck.Gen.frequency
886+
[(1, (QCheck.Gen.pure Foo));
887+
(1,
888+
(QCheck.Gen.map (fun gen0 -> Bar { baz = gen0 })
889+
(gen_sized (n / 2))))]];
890+
[%stri let gen = QCheck.Gen.sized gen_sized];
891+
[%stri let arb_sized n = QCheck.make @@ (gen_sized n)];
892+
[%stri let arb = QCheck.make @@ gen];
893+
]
894+
in
895+
let actual = f @@ extract [%stri type t = Foo | Bar of { baz : t }]
896+
in
897+
check_eq ~expected ~actual "deriving rec type in a type constructor inside record"
863898

864899
let () =
865900
Alcotest.(
@@ -907,5 +942,13 @@ let () =
907942
"deriving variant with unused fuel parameter"
908943
`Quick
909944
test_unused_variable;
945+
test_case
946+
"deriving rec type in a type constructor inside variant"
947+
`Quick
948+
test_faulty_is_rec_typ_in_variant;
949+
test_case
950+
"deriving rec type in a type constructor inside record"
951+
`Quick
952+
test_faulty_is_rec_constr_decl;
910953
] );
911954
])

0 commit comments

Comments
 (0)