From 7641a9480702a91f271de52ce8bb1d9dd73f7121 Mon Sep 17 00:00:00 2001 From: odersky Date: Tue, 7 May 2024 21:38:33 +0200 Subject: [PATCH 1/2] Unbreak the build For some reason, BestEffortTastyWriter does not compile since PlainFile does not have a delete method, only File does. --- .../dotty/tools/dotc/core/tasty/BestEffortTastyWriter.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/BestEffortTastyWriter.scala b/compiler/src/dotty/tools/dotc/core/tasty/BestEffortTastyWriter.scala index 9cdfb042b8fb..7a170b5c0cfb 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/BestEffortTastyWriter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/BestEffortTastyWriter.scala @@ -18,12 +18,13 @@ object BestEffortTastyWriter: unit.pickled.foreach { (clz, binary) => val parts = clz.fullName.mangledString.split('.') val outPath = outputPath(parts.toList, dir) - val outTastyFile = new PlainFile(new File(outPath)) + val file = new File(outPath) + val outTastyFile = new PlainFile(file) val outstream = new DataOutputStream(outTastyFile.bufferedOutput) try outstream.write(binary()) catch case ex: ClosedByInterruptException => try - outTastyFile.delete() // don't leave an empty or half-written tastyfile around after an interrupt + file.delete() // don't leave an empty or half-written tastyfile around after an interrupt catch case _: Throwable => throw ex From ae74dcf9b8d1e3f53c089c13ae4a7ed125012b52 Mon Sep 17 00:00:00 2001 From: EnzeXing Date: Mon, 27 May 2024 10:38:00 -0400 Subject: [PATCH 2/2] Fixed accessing objects and add deadlock test --- .../tools/dotc/transform/init/Objects.scala | 2 +- tests/init-global/warn/cyclic-object.scala | 9 +++++++ tests/init-global/warn/deadlock.scala | 26 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/init-global/warn/cyclic-object.scala create mode 100644 tests/init-global/warn/deadlock.scala diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 52e90c0857ed..380276021d8e 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -865,7 +865,7 @@ class Objects(using Context @constructorOnly): Bottom case Bottom => - if field.isStaticObject then ObjectRef(field.moduleClass.asClass) + if field.isStaticObject then accessObject(field.moduleClass.asClass) else Bottom case ValueSet(values) => diff --git a/tests/init-global/warn/cyclic-object.scala b/tests/init-global/warn/cyclic-object.scala new file mode 100644 index 000000000000..e997d3259877 --- /dev/null +++ b/tests/init-global/warn/cyclic-object.scala @@ -0,0 +1,9 @@ +package cyclicObject + +object O1 { // warn + val o = cyclicObject.O2 +} + +object O2 { + val o = cyclicObject.O1 +} diff --git a/tests/init-global/warn/deadlock.scala b/tests/init-global/warn/deadlock.scala new file mode 100644 index 000000000000..d39c572599af --- /dev/null +++ b/tests/init-global/warn/deadlock.scala @@ -0,0 +1,26 @@ +// example of cyclic initialization causing deadlock + +package pkg + +object Main extends App { + val createPredef = new Runnable { def run = { val _ = Predef } } + val createSeq = new Runnable { def run = { val _ = Seq } } + new Thread(createPredef).start() + new Thread(createSeq).start() + Thread.sleep(100) + val seq = Predef.seq + val predef = Seq.predef + println("done") +} + +object Predef { // warn + Thread.sleep(10) + val seq = Seq + println("done Predef") +} + +object Seq { + Thread.sleep(10) + val predef = Predef + println("done Seq") +}