@@ -431,3 +431,122 @@ val get : 'a @ contended -> 'a t1 = <fun>
431
431
type 'a t2 = { z : 'a @@ shared ; }
432
432
val get : 'a @ shared -> 'a t2 = < fun>
433
433
|}]
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