Skip to content

Commit eb54885

Browse files
authored
flambda-backend: Closing over argument crosses modes (#2305)
1 parent ff8ff9b commit eb54885

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

testsuite/tests/typing-local/crossing.ml

+10-1
Original file line numberDiff line numberDiff line change
@@ -449,4 +449,13 @@ let foo () =
449449
()
450450
[%%expect{|
451451
val foo : unit -> unit = <fun>
452-
|}]
452+
|}]
453+
454+
(* Values crosses modes when pattern-matching, an implication is that, closing
455+
over [local int] won't force the closure to be [local]. *)
456+
let foo (local_ x : int) =
457+
let bar y = x + y in
458+
ref bar
459+
[%%expect{|
460+
val foo : local_ int -> (int -> int) ref = <fun>
461+
|}]

testsuite/tests/typing-local/local.ml

+7
Original file line numberDiff line numberDiff line change
@@ -2783,6 +2783,13 @@ let f () = ((fun x -> (fun y -> "") [@extension.curry])
27832783
val f : unit -> local_ string -> (string -> string) = <fun>
27842784
|}];;
27852785
2786+
(* mode crossing - the inner closure is [global] despite closing over [local_
2787+
int] *)
2788+
let f () = ((fun x y -> x + y) : (local_ int -> (int -> int)));;
2789+
[%%expect{|
2790+
val f : unit -> local_ int -> (int -> int) = <fun>
2791+
|}];;
2792+
27862793
(* Illegal: the expected mode is global *)
27872794
let f () = local_ ((fun x y -> x + y) : (_ -> _));;
27882795
[%%expect{|

typing/typecore.ml

+15
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,18 @@ let mode_cross_to_min env ty mode =
804804
else
805805
Value.disallow_right mode
806806

807+
(* cross the monadic fragment to max, and the comonadic fragment to min *)
808+
let alloc_mode_cross_to_max_min env ty {monadic; comonadic} =
809+
let (monadic, comonadic)=
810+
if mode_cross env ty then
811+
Alloc.Monadic.max, Alloc.Comonadic.min
812+
else
813+
monadic, comonadic
814+
in
815+
let monadic = Alloc.Monadic.disallow_left monadic in
816+
let comonadic = Alloc.Comonadic.disallow_right comonadic in
817+
{monadic; comonadic}
818+
807819
let expect_mode_cross env ty (expected_mode : expected_mode) =
808820
if mode_cross env ty then
809821
{ expected_mode with
@@ -6676,6 +6688,9 @@ and type_function
66766688
Final_arg
66776689
| Some fun_alloc_mode ->
66786690
assert(not is_final_val_param);
6691+
(* If the argument cross modes, it crosses to max on monadic
6692+
axes, and min on comonadic axes. *)
6693+
let arg_mode = alloc_mode_cross_to_max_min env ty_arg arg_mode in
66796694
begin match
66806695
Alloc.submode (Alloc.close_over arg_mode) fun_alloc_mode
66816696
with

0 commit comments

Comments
 (0)