@@ -561,6 +561,93 @@ class TestBCode extends DottyBytecodeTest {
561
561
}
562
562
}
563
563
564
+ /* Test that vals in traits cause appropriate `releaseFence()` calls to be emitted. */
565
+
566
+ private def checkReleaseFence (releaseFenceExpected : Boolean , outputClassName : String , source : String ): Unit = {
567
+ checkBCode(source) { dir =>
568
+ val clsIn = dir.lookupName(outputClassName, directory = false )
569
+ val clsNode = loadClassNode(clsIn.input)
570
+ val method = getMethod(clsNode, " <init>" )
571
+
572
+ val hasReleaseFence = instructionsFromMethod(method).exists {
573
+ case Invoke (_, _, " releaseFence" , _, _) => true
574
+ case _ => false
575
+ }
576
+
577
+ assertEquals(source, releaseFenceExpected, hasReleaseFence)
578
+ }
579
+ }
580
+
581
+ @ Test def testInsertReleaseFence (): Unit = {
582
+ // An empty trait does not cause a releaseFence.
583
+ checkReleaseFence(false , " Bar.class" ,
584
+ """ trait Foo {
585
+ |}
586
+ |class Bar extends Foo
587
+ """ .stripMargin)
588
+
589
+ // A val in a class does not cause a releaseFence.
590
+ checkReleaseFence(false , " Bar.class" ,
591
+ """ trait Foo {
592
+ |}
593
+ |class Bar extends Foo {
594
+ | val x: Int = 5
595
+ |}
596
+ """ .stripMargin)
597
+
598
+ // A val in a trait causes a releaseFence.
599
+ checkReleaseFence(true , " Bar.class" ,
600
+ """ trait Foo {
601
+ | val x: Int = 5
602
+ |}
603
+ |class Bar extends Foo
604
+ """ .stripMargin)
605
+
606
+ // The presence of a var in the trait does not invalidate the need for a releaseFence.
607
+ // Also, indirect mixin.
608
+ checkReleaseFence(true , " Bar.class" ,
609
+ """ trait Parent {
610
+ | val x: Int = 5
611
+ | var y: Int = 6
612
+ |}
613
+ |trait Foo extends Parent
614
+ |class Bar extends Foo
615
+ """ .stripMargin)
616
+
617
+ // The presence of a var in the class does not invalidate the need for a releaseFence.
618
+ checkReleaseFence(true , " Bar.class" ,
619
+ """ trait Foo {
620
+ | val x: Int = 5
621
+ |}
622
+ |class Bar extends Foo {
623
+ | var y: Int = 6
624
+ |}
625
+ """ .stripMargin)
626
+
627
+ // When inheriting trait vals through a superclass, no releaseFence is inserted.
628
+ checkReleaseFence(false , " Bar.class" ,
629
+ """ trait Parent {
630
+ | val x: Int = 5
631
+ | var y: Int = 6
632
+ |}
633
+ |class Foo extends Parent // releaseFence in Foo, but not in Bar
634
+ |class Bar extends Foo
635
+ """ .stripMargin)
636
+
637
+ // Various other stuff that do not cause a releaseFence.
638
+ checkReleaseFence(false , " Bar.class" ,
639
+ """ trait Foo {
640
+ | var w: Int = 1
641
+ | final val x = 2
642
+ | def y: Int = 3
643
+ | lazy val z: Int = 4
644
+ |
645
+ | def add(a: Int, b: Int): Int = a + b
646
+ |}
647
+ |class Bar extends Foo
648
+ """ .stripMargin)
649
+ }
650
+
564
651
/* Test that objects compile to *final* classes. */
565
652
566
653
private def checkFinalClass (outputClassName : String , source : String ) = {
0 commit comments