Skip to content

Commit 38189b5

Browse files
authored
Merge pull request #5932 from dotty-staging/fix-5924
Fix #5924: don't move static to interfaces
2 parents 6bc5052 + ca0da0f commit 38189b5

File tree

8 files changed

+108
-7
lines changed

8 files changed

+108
-7
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,9 @@ trait BCodeSkelBuilder extends BCodeHelpers {
231231
val javagensig = getGenericSignature(f, claszSymbol)
232232
val flags = javaFieldFlags(f)
233233

234+
assert(!f.isStaticMember || !claszSymbol.isInterface || !f.isMutable,
235+
s"interface $claszSymbol cannot have non-final static field $f")
236+
234237
val jfield = new asm.tree.FieldNode(
235238
flags,
236239
f.javaSimpleName.toString,

compiler/src/dotty/tools/dotc/transform/LazyVals.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
3636

3737
override def changesMembers: Boolean = true // the phase adds lazy val accessors
3838

39-
def transformer: LazyVals = new LazyVals
40-
4139
val containerFlags: FlagSet = Synthetic | Mutable | Lazy
4240
val initFlags: FlagSet = Synthetic | Method
4341

compiler/src/dotty/tools/dotc/transform/MoveStatics.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ class MoveStatics extends MiniPhase with SymTransformer {
2424
override def phaseName: String = MoveStatics.name
2525

2626
def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = {
27-
if (sym.hasAnnotation(defn.ScalaStaticAnnot) && sym.owner.is(Flags.Module) && sym.owner.companionClass.exists) {
27+
if (sym.hasAnnotation(defn.ScalaStaticAnnot) && sym.owner.is(Flags.Module) && sym.owner.companionClass.exists &&
28+
(sym.is(Flags.Method) || !(sym.is(Flags.Mutable) && sym.owner.companionClass.is(Flags.Trait)))) {
2829
sym.owner.asClass.delete(sym.symbol)
2930
sym.owner.companionClass.asClass.enter(sym.symbol)
30-
val flags = if (sym.is(Flags.Method)) sym.flags else sym.flags | Flags.Mutable
31-
sym.copySymDenotation(owner = sym.owner.companionClass, initFlags = flags)
31+
sym.copySymDenotation(owner = sym.owner.companionClass)
3232
}
3333
else sym
3434
}
@@ -58,11 +58,11 @@ class MoveStatics extends MiniPhase with SymTransformer {
5858
}
5959

6060
def move(module: TypeDef, companion: TypeDef): List[Tree] = {
61-
assert(companion ne module)
61+
assert(companion != module)
6262
if (!module.symbol.is(Flags.Module)) move(companion, module)
6363
else {
6464
val allMembers =
65-
(if(companion ne null) {companion.rhs.asInstanceOf[Template].body} else Nil) ++
65+
(if(companion != null) {companion.rhs.asInstanceOf[Template].body} else Nil) ++
6666
module.rhs.asInstanceOf[Template].body
6767
val (newModuleBody, newCompanionBody) = allMembers.partition(x => {assert(x.symbol.exists); x.symbol.owner == module.symbol})
6868
Trees.flatten(rebuild(companion, newCompanionBody) :: rebuild(module, newModuleBody) :: Nil)

compiler/test/dotty/tools/backend/jvm/DottyBytecodeTest.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ trait DottyBytecodeTest {
7373
classNode.methods.asScala.find(_.name == name) getOrElse
7474
sys.error(s"Didn't find method '$name' in class '${classNode.name}'")
7575

76+
protected def getField(classNode: ClassNode, name: String): FieldNode =
77+
classNode.fields.asScala.find(_.name == name) getOrElse
78+
sys.error(s"Didn't find field '$name' in class '${classNode.name}'")
79+
7680
def diffInstructions(isa: List[Instruction], isb: List[Instruction]): String = {
7781
val len = Math.max(isa.length, isb.length)
7882
val sb = new StringBuilder

compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,4 +695,63 @@ class TestBCode extends DottyBytecodeTest {
695695
"`test` was not properly generated\n" + diffInstructions(instructions, expected))
696696
}
697697
}
698+
699+
@Test def i5924b = {
700+
val source =
701+
"""|import scala.annotation.static
702+
|trait Base
703+
|
704+
|object Base {
705+
| @static val x = 10
706+
| @static final val y = 10
707+
| @static def f: Int = 30
708+
|}
709+
""".stripMargin
710+
711+
checkBCode(source) { dir =>
712+
val clsIn = dir.lookupName("Base.class", directory = false).input
713+
val clsNode = loadClassNode(clsIn)
714+
val f = getMethod(clsNode, "f")
715+
val x = getField(clsNode, "x")
716+
val y = getField(clsNode, "y")
717+
assert((f.access & Opcodes.ACC_STATIC) != 0)
718+
List(x, y).foreach { node =>
719+
assert((node.access & Opcodes.ACC_STATIC) != 0)
720+
assert((node.access & Opcodes.ACC_FINAL) != 0)
721+
}
722+
}
723+
}
724+
725+
@Test def i5924c = {
726+
val source =
727+
"""|import scala.annotation.static
728+
|class Base
729+
|
730+
|object Base {
731+
| @static val x = 10
732+
| @static final val y = 10
733+
| @static var a = 10
734+
| @static final var b = 10
735+
| @static def f: Int = 30
736+
|}
737+
""".stripMargin
738+
739+
checkBCode(source) { dir =>
740+
val clsIn = dir.lookupName("Base.class", directory = false).input
741+
val clsNode = loadClassNode(clsIn)
742+
val f = getMethod(clsNode, "f")
743+
val x = getField(clsNode, "x")
744+
val y = getField(clsNode, "y")
745+
val a = getField(clsNode, "a")
746+
val b = getField(clsNode, "b")
747+
assert((f.access & Opcodes.ACC_STATIC) != 0)
748+
List(x, y).foreach { node =>
749+
assert((node.access & Opcodes.ACC_STATIC) != 0)
750+
assert((node.access & Opcodes.ACC_FINAL) != 0)
751+
}
752+
List(a, b).foreach { node =>
753+
assert((node.access & Opcodes.ACC_STATIC) != 0)
754+
}
755+
}
756+
}
698757
}

tests/run/i5924.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
trait Matchers {
2+
object Helper
3+
}
4+
5+
object Matchers extends Matchers
6+
7+
object Test {
8+
def main(args: Array[String]): Unit = Matchers
9+
}

tests/run/i5924b.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.annotation.static
2+
3+
trait Base
4+
5+
object Base {
6+
@static val x = 10
7+
@static final val y = 10
8+
@static def f: Int = 30
9+
}
10+
11+
object Test {
12+
def main(args: Array[String]): Unit = Base
13+
}

tests/run/i5924c.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import scala.annotation.static
2+
3+
class Base
4+
5+
object Base {
6+
@static val x = 10
7+
@static final val y = 10
8+
@static var a = 10
9+
@static final var b = 10
10+
@static def f: Int = 30
11+
}
12+
13+
object Test {
14+
def main(args: Array[String]): Unit = Base
15+
}

0 commit comments

Comments
 (0)