Skip to content

Commit 85bfd0f

Browse files
committed
ppx: explicitly disallow polymorphic method
1 parent 511185e commit 85bfd0f

File tree

2 files changed

+69
-38
lines changed

2 files changed

+69
-38
lines changed

ppx/ppx_js/lib_internal/ppx_js_internal.ml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -465,12 +465,10 @@ let new_object constr args =
465465

466466
module S = Map.Make (String)
467467

468-
(** We remove Pexp_poly as it should never be in the parsetree except after a method call.
469-
*)
470-
let format_meth body =
468+
let drop_pexp_poly body =
471469
match body.pexp_desc with
472-
| Pexp_poly (e, _) -> e
473-
| _ -> body
470+
| Pexp_poly (e, ty) -> e, ty
471+
| _ -> body, None
474472

475473
(** Ensure basic sanity rules about fields of a literal object:
476474
- No duplicated declaration
@@ -582,7 +580,7 @@ let preprocess_literal_object mappper fields :
582580
names, Val (id, kind, bang, body) :: fields
583581
| Pcf_method (id, priv, Cfk_concrete (bang, body)) ->
584582
let names = check_name id names in
585-
let body = format_meth (mappper body) in
583+
let body, body_ty = drop_pexp_poly (mappper body) in
586584
let rec create_meth_ty exp =
587585
match exp.pexp_desc with
588586
| Pexp_fun (label, _, _, body) -> Arg.make ~label () :: create_meth_ty body
@@ -591,6 +589,13 @@ let preprocess_literal_object mappper fields :
591589
| _ -> []
592590
in
593591
let fun_ty = create_meth_ty body in
592+
let body =
593+
match body_ty with
594+
| None -> body
595+
| Some { ptyp_desc = Ptyp_poly _; _ } ->
596+
raise_errorf ~loc:exp.pcf_loc "Polymorphic method not supported."
597+
| Some ty -> Exp.constraint_ body ty
598+
in
594599
names, Meth (id, priv, bang, body, fun_ty) :: fields
595600
| _ ->
596601
raise_errorf

ppx/ppx_js/tests/gen.mlt

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -351,48 +351,74 @@ let o () =
351351
end
352352

353353
[%%expect {|
354-
let o () =
355-
(fun (type res) ->
356-
fun (type t24) ->
357-
fun (type t25) ->
358-
fun (t25 : res Js_of_ocaml.Js.t -> t24 -> t25)
359-
(_ :
360-
res Js_of_ocaml.Js.t ->
361-
(res Js_of_ocaml.Js.t -> t24 -> t25 Js_of_ocaml.Js.meth) ->
362-
res)
363-
: res Js_of_ocaml.Js.t->
364-
Js_of_ocaml.Js.Unsafe.obj
365-
[|("m1",
366-
(Js_of_ocaml.Js.Unsafe.inject
367-
(Js_of_ocaml.Js.wrap_meth_callback t25)))|])
368-
(fun _ a -> ignore a) ((fun self m1 -> object method m1 = m1 self end)
369-
[@merlin.hide ]);;
370-
val o : unit -> < m1 : 't24 -> unit Js_of_ocaml.Js.meth > Js_of_ocaml.Js.t =
371-
<fun>
354+
let o () = [%ocaml.error "Polymorphic method not supported."];;
355+
Line _, characters 4-50:
356+
Error: Polymorphic method not supported.
372357
|}]
373358

374359
let o () =
375360
object%js
376361
method m1 : 'a. 'a -> unit = fun (type a) (a : a) -> ignore a
377362
end
378363

364+
[%%expect {|
365+
let o () = [%ocaml.error "Polymorphic method not supported."];;
366+
Line _, characters 4-65:
367+
Error: Polymorphic method not supported.
368+
|}]
369+
370+
371+
let o () =
372+
object%js
373+
method m1 : 'a -> unit = fun (type a) (a : a) -> ignore a
374+
method m2 : int -> unit = fun (type a) (a : a) -> ignore a
375+
method m3 : 'b -> unit = fun (a : 'b) -> ignore a
376+
end
377+
379378
[%%expect {|
380379
let o () =
381380
(fun (type res) ->
382381
fun (type t26) ->
383382
fun (type t27) ->
384-
fun (t27 : res Js_of_ocaml.Js.t -> t26 -> t27)
385-
(_ :
386-
res Js_of_ocaml.Js.t ->
387-
(res Js_of_ocaml.Js.t -> t26 -> t27 Js_of_ocaml.Js.meth) ->
388-
res)
389-
: res Js_of_ocaml.Js.t->
390-
Js_of_ocaml.Js.Unsafe.obj
391-
[|("m1",
392-
(Js_of_ocaml.Js.Unsafe.inject
393-
(Js_of_ocaml.Js.wrap_meth_callback t27)))|])
394-
(fun _ (type a) (a : a) -> ignore a)
395-
((fun self m1 -> object method m1 = m1 self end)[@merlin.hide ]);;
396-
val o : unit -> < m1 : 't26 -> unit Js_of_ocaml.Js.meth > Js_of_ocaml.Js.t =
397-
<fun>
383+
fun (type t28) ->
384+
fun (type t29) ->
385+
fun (type t30) ->
386+
fun (type t31) ->
387+
fun (t29 : res Js_of_ocaml.Js.t -> t26 -> t29)
388+
(t30 : res Js_of_ocaml.Js.t -> t27 -> t30)
389+
(t31 : res Js_of_ocaml.Js.t -> t28 -> t31)
390+
(_ :
391+
res Js_of_ocaml.Js.t ->
392+
(res Js_of_ocaml.Js.t ->
393+
t26 -> t29 Js_of_ocaml.Js.meth)
394+
->
395+
(res Js_of_ocaml.Js.t ->
396+
t27 -> t30 Js_of_ocaml.Js.meth)
397+
->
398+
(res Js_of_ocaml.Js.t ->
399+
t28 -> t31 Js_of_ocaml.Js.meth)
400+
-> res)
401+
: res Js_of_ocaml.Js.t->
402+
Js_of_ocaml.Js.Unsafe.obj
403+
[|("m1",
404+
(Js_of_ocaml.Js.Unsafe.inject
405+
(Js_of_ocaml.Js.wrap_meth_callback t29)));
406+
("m2",
407+
(Js_of_ocaml.Js.Unsafe.inject
408+
(Js_of_ocaml.Js.wrap_meth_callback t30)));
409+
("m3",
410+
(Js_of_ocaml.Js.Unsafe.inject
411+
(Js_of_ocaml.Js.wrap_meth_callback t31)))|])
412+
(fun _ : 'a -> unit-> fun (type a) -> fun (a : a) -> ignore a)
413+
(fun _ : int -> unit-> fun (type a) -> fun (a : a) -> ignore a)
414+
(fun _ : 'b -> unit-> fun (a : 'b) -> ignore a)
415+
((fun self m1 m2 m3 ->
416+
object method m1 = m1 self method m2 = m2 self method m3 = m3 self
417+
end)[@merlin.hide ]);;
418+
val o :
419+
unit ->
420+
< m1 : 't26 -> unit Js_of_ocaml.Js.meth;
421+
m2 : int -> unit Js_of_ocaml.Js.meth;
422+
m3 : 't28 -> unit Js_of_ocaml.Js.meth >
423+
Js_of_ocaml.Js.t = <fun>
398424
|}]

0 commit comments

Comments
 (0)