Skip to content

Commit

Permalink
Merge pull request scala#15707 from WojciechMazur/fix/i10835-final-vars
Browse files Browse the repository at this point in the history
Set ACC_FINAL access flag to final variable accessors
  • Loading branch information
WojciechMazur authored Aug 4, 2022
2 parents da2d44a + 51be2dd commit cfd91d4
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ class BTypesFromSymbols[I <: DottyBackendInterface](val int: I) extends BTypes {
// tests/run/serialize.scala and https://github.com/typelevel/cats-effect/pull/2360).
val privateFlag = !sym.isClass && (sym.is(Private) || (sym.isPrimaryConstructor && sym.owner.isTopLevelModuleClass))

val finalFlag = sym.is(Final) && !toDenot(sym).isClassConstructor && !sym.is(Mutable) && !sym.enclosingClass.is(Trait)
val finalFlag = sym.is(Final) && !toDenot(sym).isClassConstructor && !sym.is(Mutable, butNot = Accessor) && !sym.enclosingClass.is(Trait)

import asm.Opcodes._
import GenBCodeOps.addFlagIf
Expand Down
23 changes: 23 additions & 0 deletions compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1557,6 +1557,29 @@ class DottyBytecodeTests extends DottyBytecodeTest {
}
}

/** Check that final mutable var accessors are final */
@Test def i10835 = {
val source =
s"""class A {
| final var x = 1
|}
|""".stripMargin
checkBCode(source){dir =>
val clsIn = dir.lookupName("A.class", directory = false).input
val clsNode = loadClassNode(clsIn)
def isFinal(access: Int) = (access & Opcodes.ACC_FINAL) != 0

val field = clsNode.fields.asScala.find(_.name == "x").map(_.access)
assertTrue("field is not final", field.exists(!isFinal(_)))
assertTrue("field is private", field.exists(acc => (acc & Opcodes.ACC_PRIVATE) != 0))

val methods = clsNode.methods.asScala
def methodAccess(name: String) = methods.find(_.name == name).map(_.access)
assertTrue("getter is final", methodAccess("x").exists(isFinal))
assertTrue("setter is final", methodAccess("x_$eq").exists(isFinal))
}
}

/** Check that erasure if `Int | Nothing` is `int` */
@Test def i14970 = {
val source =
Expand Down

0 comments on commit cfd91d4

Please sign in to comment.