Skip to content

Commit bbdff6b

Browse files
yielding tests
1 parent 1565328 commit bbdff6b

File tree

1 file changed

+121
-9
lines changed

1 file changed

+121
-9
lines changed

testsuite/tests/typing-modes/yielding.ml

+121-9
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ let with_effect : ((string -> unit) @ local yielding -> 'a) -> 'a =
1818

1919
[%%expect{|
2020
val storage : string ref = {contents = ""}
21-
val with_effect : (local_ (string -> unit) @ yielding -> 'a) -> 'a = <fun>
21+
val with_effect : (local_ (string -> unit) -> 'a) -> 'a = <fun>
2222
|}]
2323

2424
let () = with_effect (fun k -> k "Hello, world!")
@@ -36,7 +36,7 @@ let () = with_effect (fun k -> run_yielding k)
3636
let _ = !storage
3737

3838
[%%expect{|
39-
val run_yielding : local_ (string -> unit) @ yielding -> unit = <fun>
39+
val run_yielding : local_ (string -> unit) -> unit = <fun>
4040
- : string = "my string"
4141
|}]
4242

@@ -45,25 +45,19 @@ let run_unyielding : (string -> unit) @ local unyielding -> unit = fun f -> f "a
4545
let () = with_effect (fun k -> run_unyielding k)
4646

4747
[%%expect{|
48-
val run_unyielding : local_ (string -> unit) -> unit = <fun>
48+
val run_unyielding : local_ (string -> unit) @ unyielding -> unit = <fun>
4949
Line 3, characters 46-47:
5050
3 | let () = with_effect (fun k -> run_unyielding k)
5151
^
5252
Error: This value is "yielding" but expected to be "unyielding".
5353
|}]
5454

55-
(* CR dkalinichenko: default [local] arguments to [yielding]. *)
56-
5755
let run_default : (string -> unit) @ local -> unit = fun f -> f "some string"
5856

5957
let () = with_effect (fun k -> run_default k)
6058

6159
[%%expect{|
6260
val run_default : local_ (string -> unit) -> unit = <fun>
63-
Line 3, characters 43-44:
64-
3 | let () = with_effect (fun k -> run_default k)
65-
^
66-
Error: This value is "yielding" but expected to be "unyielding".
6761
|}]
6862

6963
(* A closure over a [yielding] value must be [yielding]. *)
@@ -78,3 +72,121 @@ Line 2, characters 45-46:
7872
^
7973
Error: The value "k" is yielding, so cannot be used inside a function that may not yield.
8074
|}]
75+
76+
77+
type 'a t1 = Mk1 of 'a @@ global
78+
79+
type 'a t2 = Mk2 of 'a @@ global yielding
80+
81+
type 'a t3 = Mk3 of 'a @@ unyielding
82+
83+
type 'a t4 = Mk4 of 'a @@ yielding
84+
85+
let with_global_effect : ((string -> unit) @ yielding -> 'a) -> 'a =
86+
fun f -> f ((:=) storage)
87+
88+
[%%expect{|
89+
type 'a t1 = Mk1 of global_ 'a
90+
type 'a t2 = Mk2 of global_ 'a @@ yielding
91+
type 'a t3 = Mk3 of 'a @@ unyielding
92+
type 'a t4 = Mk4 of 'a
93+
val with_global_effect : ((string -> unit) @ yielding -> 'a) -> 'a = <fun>
94+
|}]
95+
96+
(* [global] modality implies [unyielding]. *)
97+
let _ = with_global_effect (fun k -> let _ = Mk1 k in ())
98+
99+
[%%expect{|
100+
Line 1, characters 49-50:
101+
1 | let _ = with_global_effect (fun k -> let _ = Mk1 k in ())
102+
^
103+
Error: This value is "yielding" but expected to be "unyielding".
104+
|}]
105+
106+
(* [global yielding] works: *)
107+
let _ = with_global_effect (fun k -> let _ = Mk2 k in ())
108+
109+
[%%expect{|
110+
- : unit = ()
111+
|}]
112+
113+
(* [unyielding] and [yielding] modalities: *)
114+
let _ = with_global_effect (fun k -> let _ = Mk3 k in ())
115+
116+
[%%expect{|
117+
Line 1, characters 49-50:
118+
1 | let _ = with_global_effect (fun k -> let _ = Mk3 k in ())
119+
^
120+
Error: This value is "yielding" but expected to be "unyielding".
121+
|}]
122+
123+
let _ = with_global_effect (fun k -> let _ = Mk4 k in ())
124+
125+
[%%expect{|
126+
- : unit = ()
127+
|}]
128+
129+
(* [@local_opt] and [yielding]: *)
130+
131+
external id : ('a[@local_opt]) -> ('a[@local_opt]) = "%identity"
132+
133+
let f1 x = id x
134+
let f2 (x @ local) = exclave_ id x
135+
let f3 (x @ yielding) = id x
136+
let f4 (x @ local unyielding) = exclave_ id x
137+
138+
[%%expect{|
139+
external id : ('a [@local_opt]) -> ('a [@local_opt]) = "%identity"
140+
val f1 : 'a -> 'a = <fun>
141+
val f2 : local_ 'a -> local_ 'a = <fun>
142+
val f3 : 'a @ yielding -> 'a @ yielding = <fun>
143+
val f4 : local_ 'a @ unyielding -> local_ 'a @ unyielding = <fun>
144+
|}]
145+
146+
(* [mod global] implies [mod unyielding] by default. *)
147+
148+
type ('a : value mod global) u1
149+
150+
type ('a : value mod global yielding) u2
151+
152+
type w1 : value mod global yielding
153+
154+
type w2 : value mod global unyielding
155+
156+
[%%expect{|
157+
type ('a : value mod global) u1
158+
type ('a : value mod global) u2
159+
type w1 : value mod global
160+
type w2 : value mod global
161+
|}]
162+
163+
type _z1 = w1 u1
164+
165+
[%%expect{|
166+
Line 1, characters 11-13:
167+
1 | type _z1 = w1 u1
168+
^^
169+
Error: This type "w1" should be an instance of type "('a : value mod global)"
170+
The kind of w1 is value mod global
171+
because of the definition of w1 at line 5, characters 0-35.
172+
But the kind of w1 must be a subkind of value mod global
173+
because of the definition of u1 at line 1, characters 0-31.
174+
|}]
175+
176+
type _z2 = w2 u1
177+
178+
[%%expect{|
179+
type _z2 = w2 u1
180+
|}]
181+
182+
type _z3 = w1 u2
183+
184+
[%%expect{|
185+
type _z3 = w1 u2
186+
|}]
187+
188+
type _z4 = w2 u2
189+
190+
[%%expect{|
191+
type _z4 = w2 u2
192+
|}]

0 commit comments

Comments
 (0)