@@ -331,20 +331,20 @@ type expected_mode =
331
331
}
332
332
333
333
type position_and_mode = {
334
- (* apply_position of the current application *)
335
334
apply_position : apply_position ;
336
- (* [Some m] if [position] is [Tail], where m is the mode of the surrounding
337
- function's return mode *)
335
+ (* * Runtime tail call behaviour of the application *)
338
336
region_mode : Regionality .t option ;
337
+ (* * INVARIANT: [Some m] iff [apply_position] is [Tail], where [m] is the mode
338
+ of the surrounding region *)
339
339
}
340
340
341
341
let position_and_mode_default = {
342
342
apply_position = Default ;
343
343
region_mode = None ;
344
344
}
345
345
346
- (* * The function produces two values, apply_position and region_mode.
347
- Invariant: if apply_position = Tail, then region_mode = Some .. . *)
346
+ (* * Decides the runtime tail call behaviour based on lexical structures and user
347
+ annotation . *)
348
348
let position_and_mode env (expected_mode : expected_mode ) sexp
349
349
: position_and_mode =
350
350
let fail err =
@@ -374,8 +374,9 @@ let position_and_mode env (expected_mode : expected_mode) sexp
374
374
let check_tail_call_local_returning loc env ap_mode {region_mode; _} =
375
375
match region_mode with
376
376
| Some region_mode -> begin
377
- (* This application is at the tail of a function with a region;
378
- if ap_mode is local, funct_ret_mode needs to be local as well. *)
377
+ (* This application will be performed after the current region is closed; if
378
+ ap_mode is local, the application allocates in the outer
379
+ region, and thus [region_mode] needs to be marked local as well*)
379
380
match
380
381
Regionality. submode (Regionality. of_locality ap_mode) region_mode
381
382
with
@@ -444,6 +445,9 @@ let mode_region mode =
444
445
let mode_max =
445
446
mode_default Value. max_mode
446
447
448
+ let mode_with_position mode position =
449
+ { (mode_default mode) with position }
450
+
447
451
let mode_max_with_position position =
448
452
{ mode_max with position }
449
453
@@ -504,17 +508,16 @@ let mode_exact mode =
504
508
{ (mode_default mode) with
505
509
exact = true }
506
510
507
- let mode_argument ~funct ~index ~position ~partial_app alloc_mode =
511
+ let mode_argument ~funct ~index ~position_and_mode ~partial_app alloc_mode =
508
512
let vmode = Value. of_alloc alloc_mode in
509
513
if partial_app then mode_default vmode
510
- else match funct.exp_desc, index, (position : apply_position) with
514
+ else match funct.exp_desc, index, position_and_mode. apply_position with
511
515
| Texp_ident (_, _, {val_kind =
512
516
Val_prim {Primitive. prim_name = (" %sequor" | " %sequand" )}},
513
517
Id_prim _, _), 1 , Tail ->
514
- (* The second argument to (&&) and (||) is in
515
- tail position if the call is *)
516
- (* vmode is wrong; fine because of mode crossing on boolean *)
517
- mode_return vmode
518
+ (* RHS of (&&) and (||) is at the tail of function region if the
519
+ application is. The argument mode is not constrained otherwise. *)
520
+ mode_with_position vmode (RTail (Option. get position_and_mode.region_mode, FTail ))
518
521
| Texp_ident (_ , _ , _ , Id_prim _ , _ ), _ , _ ->
519
522
(* Other primitives cannot be tail-called *)
520
523
mode_default vmode
@@ -6822,12 +6825,12 @@ and type_argument ?explanation ?recarg env (mode : expected_mode) sarg
6822
6825
unify_exp env texp ty_expected;
6823
6826
texp
6824
6827
6825
- and type_apply_arg env ~app_loc ~funct ~index ~position ~partial_app (lbl , arg ) =
6828
+ and type_apply_arg env ~app_loc ~funct ~index ~position_and_mode ~partial_app (lbl , arg ) =
6826
6829
match arg with
6827
6830
| Arg (Unknown_arg { sarg; ty_arg_mono; mode_arg; sort_arg } ) ->
6828
6831
let mode, _ = Alloc. newvar_below mode_arg in
6829
6832
let expected_mode =
6830
- mode_argument ~funct ~index ~position ~partial_app mode in
6833
+ mode_argument ~funct ~index ~position_and_mode ~partial_app mode in
6831
6834
let arg =
6832
6835
type_expect env expected_mode sarg (mk_expected ty_arg_mono)
6833
6836
in
@@ -6840,7 +6843,7 @@ and type_apply_arg env ~app_loc ~funct ~index ~position ~partial_app (lbl, arg)
6840
6843
mode_arg; wrapped_in_some; sort_arg }) ->
6841
6844
let mode, _ = Alloc. newvar_below mode_arg in
6842
6845
let expected_mode =
6843
- mode_argument ~funct ~index ~position ~partial_app mode in
6846
+ mode_argument ~funct ~index ~position_and_mode ~partial_app mode in
6844
6847
let ty_arg', vars = tpoly_get_poly ty_arg in
6845
6848
let arg =
6846
6849
if vars = [] then begin
@@ -6899,7 +6902,7 @@ and type_apply_arg env ~app_loc ~funct ~index ~position ~partial_app (lbl, arg)
6899
6902
(lbl, Arg (arg, Value. legacy, sort_arg))
6900
6903
| Omitted _ as arg -> (lbl, arg)
6901
6904
6902
- and type_application env app_loc expected_mode pm
6905
+ and type_application env app_loc expected_mode position_and_mode
6903
6906
funct funct_mode sargs ret_tvar =
6904
6907
let is_ignore funct =
6905
6908
is_prim ~name: " %ignore" funct &&
@@ -6924,12 +6927,12 @@ and type_application env app_loc expected_mode pm
6924
6927
submode ~loc: app_loc ~env ~reason: Other
6925
6928
mode_res expected_mode;
6926
6929
let arg_mode =
6927
- mode_argument ~funct ~index: 0 ~position: (pm.apply_position)
6930
+ mode_argument ~funct ~index: 0 ~position_and_mode
6928
6931
~partial_app: false arg_mode
6929
6932
in
6930
6933
let exp = type_expect env arg_mode sarg (mk_expected ty_arg) in
6931
6934
check_partial_application ~statement: false exp;
6932
- ([Nolabel , Arg (exp, arg_sort)], ty_ret, ap_mode, pm )
6935
+ ([Nolabel , Arg (exp, arg_sort)], ty_ret, ap_mode, position_and_mode )
6933
6936
| _ ->
6934
6937
let ty = funct.exp_type in
6935
6938
let ignore_labels =
@@ -6955,11 +6958,13 @@ and type_application env app_loc expected_mode pm
6955
6958
(Value. regional_to_local_alloc funct_mode) sargs ret_tvar
6956
6959
in
6957
6960
let partial_app = is_partial_apply untyped_args in
6958
- let pm = if partial_app then position_and_mode_default else pm in
6961
+ let position_and_mode =
6962
+ if partial_app then position_and_mode_default else position_and_mode
6963
+ in
6959
6964
let args =
6960
6965
List. mapi (fun index arg ->
6961
6966
type_apply_arg env ~app_loc ~funct ~index
6962
- ~position: (pm.apply_position) ~partial_app arg)
6967
+ ~position_and_mode ~partial_app arg)
6963
6968
untyped_args
6964
6969
in
6965
6970
let ty_ret, mode_ret, args =
@@ -6977,8 +6982,8 @@ and type_application env app_loc expected_mode pm
6977
6982
submode ~loc: app_loc ~env ~reason: (Application ty_ret)
6978
6983
mode_ret expected_mode;
6979
6984
6980
- check_tail_call_local_returning app_loc env ap_mode pm ;
6981
- args, ty_ret, ap_mode, pm
6985
+ check_tail_call_local_returning app_loc env ap_mode position_and_mode ;
6986
+ args, ty_ret, ap_mode, position_and_mode
6982
6987
6983
6988
and type_construct env (expected_mode : expected_mode ) loc lid sarg
6984
6989
ty_expected_explained attrs =
0 commit comments