Skip to content
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

Overwriting typing #3157

Merged
merged 36 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
cfe0418
First draft of type checking
anfelor Oct 11, 2024
d0faa26
Check in uniqueness analysis that tags stay the same during overwriting
anfelor Oct 14, 2024
876e636
Report a syntax error on overwriting anything except an allocation
anfelor Oct 14, 2024
f93e692
Merge branch 'overwriting' into overwriting-typing
anfelor Oct 16, 2024
b48eb61
Full type-checking for tuples and records
anfelor Oct 16, 2024
70ead74
Type checking fully implemented
anfelor Oct 17, 2024
345fee9
Clean up type-checking and add ability to overwrite arbitrary express…
anfelor Oct 17, 2024
945fb76
Fix checking of tags
anfelor Oct 17, 2024
c0785a4
Test (labeled) tuples
anfelor Oct 18, 2024
0de2a80
Final tests and allow overwrite of inlined records
anfelor Oct 18, 2024
fbf6e1b
Review suggestion
anfelor Oct 21, 2024
432eade
Review suggestion
anfelor Oct 21, 2024
f984a60
Review feedback: add more tests
anfelor Oct 21, 2024
b261b06
Uniqueness analysis: Change grammar of error message to indicate para…
anfelor Oct 21, 2024
ac401e7
Merge remote-tracking branch 'origin/overwriting-typing' into overwri…
anfelor Oct 21, 2024
2d2ae0b
Review feedback: Fix typo
anfelor Oct 21, 2024
7bf5cf0
Review feedback: add comments and tests
anfelor Oct 21, 2024
3518596
Merge remote-tracking branch 'origin/overwriting-typing' into overwri…
anfelor Oct 21, 2024
a2ca9af
Prevent nested allocations in overwrite
anfelor Oct 21, 2024
399581b
Review feedback: Fix comment and improve readability
anfelor Oct 21, 2024
16d6739
Review feedback: add comments, tests and nicer error messages
anfelor Oct 23, 2024
d385037
Fix nested record bug
anfelor Oct 23, 2024
2d8afdb
Improve code quality
anfelor Oct 23, 2024
288800a
Disallow overwriting of unboxed records
anfelor Oct 23, 2024
eaa0c9f
Review feedback
anfelor Oct 24, 2024
33b3634
Clarify the overwriting state for type_label_exp
goldfirere Oct 25, 2024
fd050dc
Add debugging printers for uniqueness
goldfirere Oct 25, 2024
c29a7bb
Temporarily allow unique mutable fields for better tests of overwriti…
anfelor Oct 30, 2024
3e5023e
New scheme for checking that overwrite does not change tags
anfelor Nov 4, 2024
1f23b9b
Refactor: split up Learned_tags and Overwrites and use match_with_lea…
anfelor Nov 7, 2024
f91955d
Add comment about fold_left1 and zero of semiring
anfelor Nov 7, 2024
db26890
Fix submode error attribution in records
anfelor Nov 8, 2024
cf2a211
Tune errors in tag checker
anfelor Nov 8, 2024
3ca5e8a
Don't record tags that have been overwritten and matched with a learn…
anfelor Nov 8, 2024
7447b62
Review feedback: comments and small improvements
anfelor Nov 26, 2024
5450be3
Review feedback: tune comments
anfelor Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 65 additions & 4 deletions ocaml/testsuite/tests/typing-unique/overwriting.ml
anfelor marked this conversation as resolved.
Show resolved Hide resolved
anfelor marked this conversation as resolved.
Show resolved Hide resolved
goldfirere marked this conversation as resolved.
Show resolved Hide resolved
anfelor marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -487,9 +487,70 @@ Uncaught exception: File "ocaml/parsing/location.ml", line 1106, characters 2-8:
(*******************************)
(* Overwriting inlined records *)

(* CR uniqueness *)
type constructor_update = Con of { x : string; y : string }
[%%expect{|
type constructor_update = Con of { x : string; y : string; }
|}]

let update = function
| (Con _ as c) ->
anfelor marked this conversation as resolved.
Show resolved Hide resolved
let x = overwrite_ c with Con { x = "foo" } in
x
[%%expect{|
Line 3, characters 12-47:
3 | let x = overwrite_ c with Con { x = "foo" } in
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Alert Translcore: Overwrite not implemented.
Uncaught exception: File "ocaml/parsing/location.ml", line 1106, characters 2-8: Assertion failed

|}]

(******************************)
(* Overwriting mutable fields *)
let update = function
| (Con c1 as c) ->
let x = overwrite_ c with Con { c1 with x = "foo" } in
x
[%%expect{|
Line 3, characters 12-55:
3 | let x = overwrite_ c with Con { c1 with x = "foo" } in
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Alert Translcore: Overwrite not implemented.
Uncaught exception: File "ocaml/parsing/location.ml", line 1106, characters 2-8: Assertion failed

(* CR uniqueness *)
|}]

let update = function
| (Con c) ->
let x = overwrite_ c with { x = "foo" } in
x
anfelor marked this conversation as resolved.
Show resolved Hide resolved
[%%expect{|
Line 3, characters 23-24:
3 | let x = overwrite_ c with { x = "foo" } in
^
Error: This form is not allowed as the type of the inlined record could escape.
|}]

let update = function
| (Con c) ->
let x = Con (overwrite_ c with { x = "foo" }) in
x
[%%expect{|
Line 3, characters 16-49:
3 | let x = Con (overwrite_ c with { x = "foo" }) in
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Alert Translcore: Overwrite not implemented.
Uncaught exception: File "ocaml/parsing/location.ml", line 1106, characters 2-8: Assertion failed

|}]

let update = function
| (Con c) ->
let x = Con (overwrite_ c with { c with x = "foo" }) in
x
[%%expect{|
Line 3, characters 16-56:
3 | let x = Con (overwrite_ c with { c with x = "foo" }) in
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Alert Translcore: Overwrite not implemented.
Uncaught exception: File "ocaml/parsing/location.ml", line 1106, characters 2-8: Assertion failed

|}]
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,22 @@ let swap_inner (t : tree) =
val swap_inner : tree -> tree @@ global many = <fun>
|}]

(* CR uniqueness: Update this test once overwriting is fully implemented.
let swap_inner (t : tree) =
match t with
| Node { l = Node { r = lr } as l; r = Node { l = rl } as r } as t ->
overwrite_ t with
Node { l = overwrite_ l with Node { r = rl; };
r = overwrite_ r with Node { l = lr; }}
| _ -> t
[%%expect{|

|}]
*)

(***********************)
(* Barriers for guards *)

let match_guard r =
match r with
| { y } when String.equal y "" ->
Expand Down Expand Up @@ -376,15 +392,69 @@ Line 3, characters 41-42:

|}]

(* CR uniqueness: Update this test once overwriting is fully implemented.
let swap_inner (t : tree) =
match t with
| Node { l = Node { r = lr } as l; r = Node { l = rl } as r } as t ->
overwrite_ t with
Node { l = overwrite_ l with Node { r = rl; };
r = overwrite_ r with Node { l = lr; }}
| _ -> t
(********************************************)
(* Global allocations in overwritten fields *)
anfelor marked this conversation as resolved.
Show resolved Hide resolved

type option_record = { x : string option; y : string option @@ many aliased }
[%%expect{|
0
type option_record = {
x : string option;
y : string option @@ many aliased;
}
|}]

let check_heap_alloc_in_overwrite (unique_ r : option_record) =
overwrite_ r with { x = Some "" }
[%%expect{|
Line 2, characters 2-35:
2 | overwrite_ r with { x = Some "" }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Alert Translcore: Overwrite not implemented.
Uncaught exception: File "ocaml/parsing/location.ml", line 1106, characters 2-8: Assertion failed

|}]

let check_heap_alloc_in_overwrite (unique_ r : option_record) =
overwrite_ r with { y = Some "" }
[%%expect{|
Line 2, characters 2-35:
2 | overwrite_ r with { y = Some "" }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Alert Translcore: Overwrite not implemented.
Uncaught exception: File "ocaml/parsing/location.ml", line 1106, characters 2-8: Assertion failed

|}]

(*******************************)
(* Overwrite of mutable fields *)

type mutable_record = { mutable x : string; y : string }
[%%expect{|
0
type mutable_record = { mutable x : string; y : string; }
|}]

let update (unique_ r : mutable_record) =
let x = overwrite_ r with { x = "foo" } in
x.x
[%%expect{|
Line 2, characters 10-41:
2 | let x = overwrite_ r with { x = "foo" } in
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Alert Translcore: Overwrite not implemented.
Uncaught exception: File "ocaml/parsing/location.ml", line 1106, characters 2-8: Assertion failed

|}]

let update (unique_ r : mutable_record) =
let x = overwrite_ r with { y = "foo" } in
x.x
[%%expect{|
Line 2, characters 10-41:
2 | let x = overwrite_ r with { y = "foo" } in
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Alert Translcore: Overwrite not implemented.
Uncaught exception: File "ocaml/parsing/location.ml", line 1106, characters 2-8: Assertion failed

|}]
*)
8 changes: 8 additions & 0 deletions ocaml/testsuite/tests/typing-unique/overwriting_syntax.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
expect;
*)

(* CR uniqueness: It would be nice to also support the following syntactic forms:
overwrite_ e with (~x:5, ..)
overwrite_ e with { x = 4; _ }

This would require us to allow general patterns as the top-level second argument to
overwrite_ with. However, all overwritten fields should continue to be expressions.
*)

(******************)
(* Usage examples *)

Expand Down
8 changes: 5 additions & 3 deletions ocaml/typing/typecore.ml
anfelor marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -6599,7 +6599,7 @@ and type_expect_
{ ty = newvar (Jkind.Builtin.value ~why:Boxed_record);
explanation = None }
in
let exp1 = type_expect env (mode_default cell_mode) exp1 cell_type in
let exp1 = type_expect ~recarg env (mode_default cell_mode) exp1 cell_type in
anfelor marked this conversation as resolved.
Show resolved Hide resolved
let exp2 =
(* The newly-written fields have to global to avoid heap-to-stack pointers.
anfelor marked this conversation as resolved.
Show resolved Hide resolved
We enforce that here, by asking the allocation to be global.
Expand All @@ -6618,7 +6618,7 @@ and type_expect_
|> Value.disallow_right
in
let overwrite = Overwriting (exp1.exp_loc, exp1.exp_type, fields_mode) in
type_expect ~overwrite env exp2_mode exp2 ty_expected_explained
type_expect ~recarg ~overwrite env exp2_mode exp2 ty_expected_explained
in
re { exp_desc = Texp_overwrite(exp1, exp2);
exp_loc = loc; exp_extra = [];
Expand Down Expand Up @@ -8148,7 +8148,9 @@ and type_construct ~overwrite env (expected_mode : expected_mode) loc lid sarg
begin match sargs with
| [{pexp_desc =
Pexp_ident _ |
Pexp_record (_, (Some {pexp_desc = Pexp_ident _}| None))}] ->
Pexp_record (_, (Some {pexp_desc = Pexp_ident _}| None)) |
Pexp_overwrite (_, {pexp_desc =
Pexp_record (_, (Some {pexp_desc = Pexp_ident _}| None))})}] ->
Required
| _ ->
raise (Error(loc, env, Inlined_record_expected))
Expand Down
Loading