Skip to content

Commit

Permalink
Make move specifier optional for known functions
Browse files Browse the repository at this point in the history
This is a big change. We now allow to make the move specifier `!`
optional when calling functions whose type is known. They arguments will
be treated as if they were passed by move. If the function type is not
known, e.g. in non-annotated function type parameters, it still is
needed for type inference.
  • Loading branch information
tjammer committed Nov 8, 2024
1 parent 1828e2a commit ce52292
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
32 changes: 28 additions & 4 deletions lib/typing/typing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,21 @@ end = struct

let string_typ = Tconstr (Path.Pmod ("string", Path.Pid "t"), [])

let mapi_with_callee_params f args callee =
let params = match repr callee.typ with Tfun (ps, _, _) -> ps | _ -> [] in
let rec aux i acc args params =
match (args, params) with
| [], _ -> List.rev acc
| arg :: atl, [] ->
let acc = f i arg None :: acc in
aux (i + 1) acc atl []
| arg :: atl, p :: ptl ->
let acc = f i arg (Some p.pattr) :: acc in
aux (i + 1) acc atl ptl
in

aux 0 [] args params

let rec convert env expr = convert_annot env None expr

and convert_annot env annot = function
Expand Down Expand Up @@ -952,15 +967,24 @@ end = struct

let annots = param_annots callee.typ in
let typed_exprs =
List.mapi
(fun i (a : Ast.argument) ->
mapi_with_callee_params
(fun i (a : Ast.argument) callee_attr ->
let e =
pass_mut_helper env a.aloc a.apass (fun () ->
convert_annot env (param_annot annots i) a.aexpr)
in
(* We also care about whether the argument _can_ be mutable, for array-get *)
(e, a.apass, e.attr.mut))
args
let attr =
match (a.apass, callee_attr) with
| Dnorm, Some Dmove ->
(* Allow move specifier [!] to be left out when calling known
functions. If we don't know the function type, the argument
needs to be passed by move explicitly. *)
Dmove
| attr, _ -> attr
in
(e, attr, e.attr.mut))
args callee
in

let args =
Expand Down
15 changes: 15 additions & 0 deletions test/typing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,19 @@ let test_func_capture_annot_wrong () =
let test_func_unused_rec () =
test_exn "Unused rec flag" "fun rec add(a) {a + 1}"

let test_func_missing_move_known () =
test "unit" "fun move(a!) { ignore(a) };move([0])"

let test_func_missing_move_unknown () =
test_exn
"In application\n\
expecting (([array[int]]) -> _) -> _\n\
but found (([array[int]!]) -> _) -> _"
{|fun move(a!) { ignore(a) }
fun apply_move(move): move([0])
apply_move(move)
|}

let test_record_clear () =
test "t" "type t = { x : int, y : int }; {x = 2, y = 2}"

Expand Down Expand Up @@ -1449,6 +1462,8 @@ let () =
case "capture annot" test_func_capture_annot;
case "capture annot wrong" test_func_capture_annot_wrong;
case "unused rec" test_func_unused_rec;
case "missing move known" test_func_missing_move_known;
case "missing move unknown" test_func_missing_move_unknown;
] );
( "records",
[
Expand Down

0 comments on commit ce52292

Please sign in to comment.