Skip to content

Commit 53fbbb7

Browse files
lazy_t tests
1 parent a1c02d0 commit 53fbbb7

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

testsuite/tests/typing-modes/statefulness-visibility.ml

+119
Original file line numberDiff line numberDiff line change
@@ -431,3 +431,122 @@ val get : 'a @ contended -> 'a t1 = <fun>
431431
type 'a t2 = { z : 'a @@ shared; }
432432
val get : 'a @ shared -> 'a t2 = <fun>
433433
|}]
434+
435+
(* Interactions with lazy values. *)
436+
437+
(* [lazy_t @ stateless] capture values at [immutable]. *)
438+
let foo (x : int ref) @ stateless = lazy (x.contents)
439+
440+
[%%expect{|
441+
Line 1, characters 42-43:
442+
1 | let foo (x : int ref) @ stateless = lazy (x.contents)
443+
^
444+
Error: This value is "immutable" but expected to be "read".
445+
Hint: In order to read from the mutable fields,
446+
this record needs to have read visibility.
447+
|}]
448+
449+
(* [lazy_t @ observing] capture values at [read]. *)
450+
451+
let bat (x : int ref) @ observing = lazy (x.contents <- 4)
452+
[%%expect{|
453+
Line 1, characters 42-43:
454+
1 | let bat (x : int ref) @ observing = lazy (x.contents <- 4)
455+
^
456+
Error: This value is "read" but expected to be "read_write".
457+
Hint: In order to write into the mutable fields,
458+
this record needs to have read_write visibility.
459+
|}]
460+
461+
let bar (x : int ref) @ observing = lazy (x.contents)
462+
463+
[%%expect{|
464+
val bar : int ref -> int lazy_t @ observing = <fun>
465+
|}]
466+
467+
let () =
468+
match bar {contents = 5} with
469+
| lazy 5 -> ()
470+
| _ -> assert false
471+
472+
[%%expect{|
473+
|}]
474+
475+
(* [contended] lazy values can't be forced. *)
476+
let fuz (x : int ref) @ observing immutable = lazy (x.contents)
477+
[%%expect{|
478+
val fuz : int ref -> int lazy_t @ observing immutable = <fun>
479+
|}]
480+
481+
let () =
482+
match fuz {contents = -1} with
483+
| lazy (-1) -> ()
484+
| _ -> assert false
485+
486+
[%%expect{|
487+
Line 3, characters 4-13:
488+
3 | | lazy (-1) -> ()
489+
^^^^^^^^^
490+
Error: This value is "contended" but expected to be "uncontended".
491+
Hint: In order to force the lazy expression,
492+
the lazy needs to be uncontended.
493+
|}]
494+
495+
(* But [immutable] lazy values can be, by design. *)
496+
let baz (x : int ref) @ observing immutable uncontended = lazy (x.contents)
497+
498+
[%%expect{|
499+
val baz : int ref -> int lazy_t @ uncontended observing immutable = <fun>
500+
|}]
501+
502+
let () =
503+
match baz {contents = 42} with
504+
| lazy 42 -> ()
505+
| _ -> assert false
506+
507+
[%%expect{|
508+
|}]
509+
510+
let zab () @ immutable uncontended = lazy (ref 5)
511+
512+
[%%expect{|
513+
val zab : unit -> int ref lazy_t @ uncontended immutable = <fun>
514+
|}]
515+
516+
(* Forcing an [immutable] lazy returns an [immutable] value. *)
517+
let () =
518+
match zab () with
519+
| lazy x ->
520+
x.contents <- 42;
521+
assert (x.contents = 42)
522+
523+
[%%expect{|
524+
Line 4, characters 4-5:
525+
4 | x.contents <- 42;
526+
^
527+
Error: This value is "immutable" but expected to be "read_write".
528+
Hint: In order to write into the mutable fields,
529+
this record needs to have read_write visibility.
530+
|}]
531+
532+
(* Forcing a [read] lazy returns a [read] value.*)
533+
let zag () @ read uncontended = lazy (ref 42)
534+
535+
[%%expect{|
536+
val zag : unit -> int ref lazy_t @ uncontended read = <fun>
537+
|}]
538+
539+
let () =
540+
match zag () with
541+
| lazy y ->
542+
assert (y.contents = 42);
543+
y.contents <- 24
544+
545+
[%%expect{|
546+
Line 5, characters 4-5:
547+
5 | y.contents <- 24
548+
^
549+
Error: This value is "read" but expected to be "read_write".
550+
Hint: In order to write into the mutable fields,
551+
this record needs to have read_write visibility.
552+
|}]

0 commit comments

Comments
 (0)