Repository navigation
Evaluate partial application arguments once #8936
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+486
−45
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
4882045
Evaluate partial application arguments once
cknitt be72a81
Bind closures and external values of partial applications too
cknitt 42e741c
Generalize a partial application only when its parts are values
cknitt ecb2c66
Format is_nonexpansive
cknitt 885afb2
Bind allocating constants of partial applications too
cknitt 4ff19a3
Test the Lambda of partial applications
cknitt e25089d
Count a nested None as an allocating constant
cknitt 9cb8b5e
Keep top-level constant blocks out of the closure that captures them
cknitt File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| - Evaluate the callee and arguments of a partial application `f(a, ...)` once, so an `await` in them no longer ends up in a non-async function. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
tests/build_tests/super_errors/expected/partial_application_value_restriction.res.expected
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
|
|
||
| [1;31mWe've found a bug for you![0m | ||
| [36m/.../fixtures/partial_application_value_restriction.res[0m:[2m6:30-33[0m | ||
|
|
||
| 4 [2m│[0m let h = first([], ...) | ||
| 5 [2m│[0m let ints: array<int> = h(0) | ||
| [1;31m6[0m [2m│[0m let strings: array<string> = [1;31mh(0)[0m | ||
| 7 [2m│[0m | ||
|
|
||
| This has type: [1;31marray<int>[0m | ||
| But it's expected to have type: [1;33marray<string>[0m | ||
|
|
||
| The incompatible parts: | ||
| [1;31mint[0m vs [1;33mstring[0m | ||
|
|
||
| You can convert [1;33mint[0m to [1;33mstring[0m with [1;33mInt.toString[0m. |
6 changes: 6 additions & 0 deletions
6
tests/build_tests/super_errors/fixtures/partial_application_value_restriction.res
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| let first = (x, _y) => x | ||
|
|
||
| // `[]` is evaluated once, so every call of `h` returns the same array | ||
| let h = first([], ...) | ||
| let ints: array<int> = h(0) | ||
| let strings: array<string> = h(0) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| let ( >:: ), ( >::: ) = OUnit.(( >:: ), ( >::: )) | ||
|
|
||
| (* The raw Lambda bound to [name] in [source]. *) | ||
| let binding_lambda ~name source = | ||
| let parsed = | ||
| Res_driver.parse_implementation_from_source | ||
| ~display_filename:"PartialApplication.res" ~source | ||
| in | ||
| OUnit.assert_bool "source parses" (not parsed.invalid); | ||
| let typed, _, _ = | ||
| Typemod.type_structure (Env.initial_safe_string ()) parsed.parsetree | ||
| in | ||
| let implementation = | ||
| Translmod.transl_implementation "PartialApplication" | ||
| (typed, Typedtree.Tcoerce_none) | ||
| in | ||
| let found = ref None in | ||
| let rec find (lam : Lambda.t) = | ||
| (match lam with | ||
| | Llet (_, id, arg, _) when Ident.name id = name -> found := Some arg | ||
| | _ -> ()); | ||
| Lambda_traverse.iter find lam | ||
| in | ||
| find implementation.lambda; | ||
| match !found with | ||
| | Some lam -> lam | ||
| | None -> OUnit.assert_failure ("no binding for " ^ name) | ||
|
|
||
| let unexpected lam = | ||
| OUnit.assert_failure ("unexpected Lambda: " ^ Printlambda.lambda_to_string lam) | ||
|
|
||
| let is_call_of name (lam : Lambda.t) = | ||
| match lam with | ||
| | Lapply {ap_func = Lvar f} -> Ident.name f = name | ||
| | _ -> false | ||
|
|
||
| let suites = | ||
| __FILE__ | ||
| >::: [ | ||
| ( "callee and arguments are bound outside the function, callee first" | ||
| >:: fun _ -> | ||
| let lam = | ||
| binding_lambda ~name:"h" | ||
| "let add = (a, _b, _c) => a\n\ | ||
| let getAdd = () => add\n\ | ||
| let next = () => 1\n\ | ||
| let h = getAdd()(next(), ...)\n" | ||
| in | ||
| match lam with | ||
| | Llet | ||
| ( Strict, | ||
| func, | ||
| callee, | ||
| Llet | ||
| ( Strict, | ||
| arg, | ||
| argument, | ||
| Lfunction | ||
| { | ||
| params = [extra1; extra2]; | ||
| body = | ||
| Lapply | ||
| { | ||
| ap_func = Lvar f; | ||
| ap_args = [Lvar a; Lvar e1; Lvar e2]; | ||
| }; | ||
| } ) ) | ||
| when is_call_of "getAdd" callee && is_call_of "next" argument -> | ||
| OUnit.assert_bool "the function calls the bound callee" | ||
| (Ident.same f func); | ||
| OUnit.assert_bool "the function passes the bound argument" | ||
| (Ident.same a arg); | ||
| OUnit.assert_bool "the remaining parameters are passed on" | ||
| (Ident.same e1 extra1 && Ident.same e2 extra2) | ||
| | lam -> unexpected lam ); | ||
| ( "variables and constants stay in the function" >:: fun _ -> | ||
| let lam = | ||
| binding_lambda ~name:"h" | ||
| "let add = (a, _b, _c) => a\nlet x = 1\nlet h = add(x, 2, ...)\n" | ||
| in | ||
| match lam with | ||
| | Lfunction | ||
| { | ||
| body = | ||
| Lapply | ||
| { | ||
| ap_func = Lvar f; | ||
| ap_args = [Lvar x; Lconst (Const_int 2l); Lvar _]; | ||
| }; | ||
| } | ||
| when Ident.name f = "add" && Ident.name x = "x" -> | ||
| () | ||
| | lam -> unexpected lam ); | ||
| ( "an allocating constant is bound outside the function" >:: fun _ -> | ||
| let lam = | ||
| binding_lambda ~name:"h" | ||
| "let first = (x, _y) => x\nlet h = first((1, 2), ...)\n" | ||
| in | ||
| match lam with | ||
| | Llet | ||
| ( Strict, | ||
| arg, | ||
| Lconst (Const_block _), | ||
| Lfunction | ||
| { | ||
| body = Lapply {ap_func = Lvar f; ap_args = [Lvar a; Lvar _]}; | ||
| } ) | ||
| when Ident.name f = "first" && Ident.same a arg -> | ||
| () | ||
| | lam -> unexpected lam ); | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.