Skip to content

Commit 07fb189

Browse files
authored
Do not emit a SYNCHRONIZED method for Outer.this.synchronized calls (#26998)
Reported by @natsukagami offline. Regression from #26697 ## Have you relied on LLM-based tools in this contribution? No ## How was the solution tested? New automated tests (including the issue's reproducer, if applicable)
1 parent b22130d commit 07fb189

4 files changed

Lines changed: 32 additions & 1 deletion

File tree

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ class SimplifySynchronized extends MiniPhase:
1717
override def transformDefDef(tree: DefDef)(using Context): Tree = {
1818
@tailrec
1919
def extractSynchronized(rhs: Tree): Option[Tree] = rhs match
20-
case Apply(TypeApply(Ident(nme.synchronized_) | Select(This(_), nme.synchronized_), _), synchronizedBody :: Nil) =>
20+
case Apply(TypeApply(Ident(nme.synchronized_), _), synchronizedBody :: Nil) =>
21+
Some(synchronizedBody)
22+
// `This(X)` means `this` inside `X` but `X.this` inside a nested class of `X`!
23+
case Apply(TypeApply(Select(t: This, nme.synchronized_), _), synchronizedBody :: Nil) if t.tpe == tree.symbol.owner.thisType =>
2124
Some(synchronizedBody)
2225
case Block(Nil, expr) =>
2326
extractSynchronized(expr)

compiler/test/dotc/scoverage-ignore.excludelist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,4 @@ spurious-overload.scala
4343
tailrec-synchronized.scala
4444
tailrec.scala
4545
traitParams.scala
46+
outer-synchronized.scala

tests/run/outer-synchronized.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
32
2+
32
3+
0

tests/run/outer-synchronized.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// scalajs: --skip
2+
// (JVM-only reflection-based test)
3+
4+
class Outer:
5+
var x = 0
6+
class Inner:
7+
def f(): Unit = Outer.this.synchronized { x += 1 }
8+
def own(): Unit = this.synchronized { x += 1 }
9+
def ownImplicit(): Unit = synchronized { x += 1 }
10+
11+
object Test:
12+
def main(args: Array[String]): Unit =
13+
val o = new Outer()
14+
val i = new o.Inner()
15+
16+
val om = o.getClass.getDeclaredMethods.find(_.getName == "own").get
17+
println(om.getModifiers & java.lang.reflect.Modifier.SYNCHRONIZED)
18+
19+
val om2 = o.getClass.getDeclaredMethods.find(_.getName == "ownImplicit").get
20+
println(om2.getModifiers & java.lang.reflect.Modifier.SYNCHRONIZED)
21+
22+
val fm = i.getClass.getDeclaredMethods.find(_.getName == "f").get
23+
println(fm.getModifiers & java.lang.reflect.Modifier.SYNCHRONIZED)
24+

0 commit comments

Comments
 (0)