From d5721f4951a7c41986123daf77c38df620500371 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Wed, 23 Dec 2020 18:39:49 +0100 Subject: [PATCH 1/5] Avoid calling show in debug println, this could crash and mask the original failure --- compiler/src/dotty/tools/dotc/core/Denotations.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 81843260bc3c..b3c96ff34c97 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -585,7 +585,7 @@ object Denotations { try info.signature catch { // !!! DEBUG case scala.util.control.NonFatal(ex) => - report.echo(s"cannot take signature of ${info.show}") + report.echo(s"cannot take signature of $info") throw ex } case _ => Signature.NotAMethod From e9f980e0648424580bb71dc132af0f170f8dac58 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Thu, 24 Dec 2020 16:00:49 +0100 Subject: [PATCH 2/5] Stop using scala.runtime.function.JFunction*mc* Instead, use the equivalent classes in the Scala 2 standard library in scala.runtime.java8. The only difference is that these classes are written in Scala instead of Java, which exposed a bug in the Scala2Unpickler: we were calling `atPhaseNoLater(picklerPhase)`, but this doesn't actually do anything in situation where the Pickler phase is not used (for example, when using the `QuoteCompiler`), this is fixed by introducing a new `atPhaseBeforeTransforms` which does the right thing. Because the `FirstTransform` phase itself might not be present, this also required fixing `Phase#next` and `Phase#prev` to work on `NoPhase`: the issue was that `myBase.NoPhase` failed with an NPE which we fix by making `NoPhase` a static object instead of a member of `PhasesBase`. Since an instace of `Phase` contains mutable state this requires making it `@sharable` to pass our tests, this is safe since we never mutate anything in `NoPhase` (this also matches what we do for `NoSymbol` and `NoDenotation`). --- .../dotty/tools/backend/sjs/JSCodeGen.scala | 4 ++-- .../dotty/tools/dotc/core/Annotations.scala | 6 ++--- .../src/dotty/tools/dotc/core/Contexts.scala | 10 ++++++++ .../src/dotty/tools/dotc/core/Phases.scala | 23 +++++++++++-------- .../tools/dotc/core/tasty/TreeUnpickler.scala | 4 ++-- .../core/unpickleScala2/Scala2Unpickler.scala | 2 +- .../dotc/transform/FunctionalInterfaces.scala | 2 +- .../runtime/function/JFunction0$mcB$sp.java | 0 .../runtime/function/JFunction0$mcC$sp.java | 0 .../runtime/function/JFunction0$mcD$sp.java | 0 .../runtime/function/JFunction0$mcF$sp.java | 0 .../runtime/function/JFunction0$mcI$sp.java | 0 .../runtime/function/JFunction0$mcJ$sp.java | 0 .../runtime/function/JFunction0$mcS$sp.java | 0 .../runtime/function/JFunction0$mcV$sp.java | 0 .../runtime/function/JFunction0$mcZ$sp.java | 0 .../runtime/function/JFunction1$mcDD$sp.java | 0 .../runtime/function/JFunction1$mcDF$sp.java | 0 .../runtime/function/JFunction1$mcDI$sp.java | 0 .../runtime/function/JFunction1$mcDJ$sp.java | 0 .../runtime/function/JFunction1$mcFD$sp.java | 0 .../runtime/function/JFunction1$mcFF$sp.java | 0 .../runtime/function/JFunction1$mcFI$sp.java | 0 .../runtime/function/JFunction1$mcFJ$sp.java | 0 .../runtime/function/JFunction1$mcID$sp.java | 0 .../runtime/function/JFunction1$mcIF$sp.java | 0 .../runtime/function/JFunction1$mcII$sp.java | 0 .../runtime/function/JFunction1$mcIJ$sp.java | 0 .../runtime/function/JFunction1$mcJD$sp.java | 0 .../runtime/function/JFunction1$mcJF$sp.java | 0 .../runtime/function/JFunction1$mcJI$sp.java | 0 .../runtime/function/JFunction1$mcJJ$sp.java | 0 .../runtime/function/JFunction1$mcVD$sp.java | 0 .../runtime/function/JFunction1$mcVF$sp.java | 0 .../runtime/function/JFunction1$mcVI$sp.java | 0 .../runtime/function/JFunction1$mcVJ$sp.java | 0 .../runtime/function/JFunction1$mcZD$sp.java | 0 .../runtime/function/JFunction1$mcZF$sp.java | 0 .../runtime/function/JFunction1$mcZI$sp.java | 0 .../runtime/function/JFunction1$mcZJ$sp.java | 0 .../runtime/function/JFunction2$mcDDD$sp.java | 0 .../runtime/function/JFunction2$mcDDI$sp.java | 0 .../runtime/function/JFunction2$mcDDJ$sp.java | 0 .../runtime/function/JFunction2$mcDID$sp.java | 0 .../runtime/function/JFunction2$mcDII$sp.java | 0 .../runtime/function/JFunction2$mcDIJ$sp.java | 0 .../runtime/function/JFunction2$mcDJD$sp.java | 0 .../runtime/function/JFunction2$mcDJI$sp.java | 0 .../runtime/function/JFunction2$mcDJJ$sp.java | 0 .../runtime/function/JFunction2$mcFDD$sp.java | 0 .../runtime/function/JFunction2$mcFDI$sp.java | 0 .../runtime/function/JFunction2$mcFDJ$sp.java | 0 .../runtime/function/JFunction2$mcFID$sp.java | 0 .../runtime/function/JFunction2$mcFII$sp.java | 0 .../runtime/function/JFunction2$mcFIJ$sp.java | 0 .../runtime/function/JFunction2$mcFJD$sp.java | 0 .../runtime/function/JFunction2$mcFJI$sp.java | 0 .../runtime/function/JFunction2$mcFJJ$sp.java | 0 .../runtime/function/JFunction2$mcIDD$sp.java | 0 .../runtime/function/JFunction2$mcIDI$sp.java | 0 .../runtime/function/JFunction2$mcIDJ$sp.java | 0 .../runtime/function/JFunction2$mcIID$sp.java | 0 .../runtime/function/JFunction2$mcIII$sp.java | 0 .../runtime/function/JFunction2$mcIIJ$sp.java | 0 .../runtime/function/JFunction2$mcIJD$sp.java | 0 .../runtime/function/JFunction2$mcIJI$sp.java | 0 .../runtime/function/JFunction2$mcIJJ$sp.java | 0 .../runtime/function/JFunction2$mcJDD$sp.java | 0 .../runtime/function/JFunction2$mcJDI$sp.java | 0 .../runtime/function/JFunction2$mcJDJ$sp.java | 0 .../runtime/function/JFunction2$mcJID$sp.java | 0 .../runtime/function/JFunction2$mcJII$sp.java | 0 .../runtime/function/JFunction2$mcJIJ$sp.java | 0 .../runtime/function/JFunction2$mcJJD$sp.java | 0 .../runtime/function/JFunction2$mcJJI$sp.java | 0 .../runtime/function/JFunction2$mcJJJ$sp.java | 0 .../runtime/function/JFunction2$mcVDD$sp.java | 0 .../runtime/function/JFunction2$mcVDI$sp.java | 0 .../runtime/function/JFunction2$mcVDJ$sp.java | 0 .../runtime/function/JFunction2$mcVID$sp.java | 0 .../runtime/function/JFunction2$mcVII$sp.java | 0 .../runtime/function/JFunction2$mcVIJ$sp.java | 0 .../runtime/function/JFunction2$mcVJD$sp.java | 0 .../runtime/function/JFunction2$mcVJI$sp.java | 0 .../runtime/function/JFunction2$mcVJJ$sp.java | 0 .../runtime/function/JFunction2$mcZDD$sp.java | 0 .../runtime/function/JFunction2$mcZDI$sp.java | 0 .../runtime/function/JFunction2$mcZDJ$sp.java | 0 .../runtime/function/JFunction2$mcZID$sp.java | 0 .../runtime/function/JFunction2$mcZII$sp.java | 0 .../runtime/function/JFunction2$mcZIJ$sp.java | 0 .../runtime/function/JFunction2$mcZJD$sp.java | 0 .../runtime/function/JFunction2$mcZJI$sp.java | 0 .../runtime/function/JFunction2$mcZJJ$sp.java | 0 94 files changed, 33 insertions(+), 18 deletions(-) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction0$mcB$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction0$mcC$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction0$mcD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction0$mcF$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction0$mcI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction0$mcJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction0$mcS$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction0$mcV$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction0$mcZ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcDD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcDF$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcDI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcDJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcFD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcFF$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcFI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcFJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcID$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcIF$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcII$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcIJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcJD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcJF$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcJI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcJJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcVD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcVF$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcVI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcVJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcZD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcZF$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcZI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1$mcZJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcDDD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcDDI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcDDJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcDID$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcDII$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcDIJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcDJD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcDJI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcDJJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcFDD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcFDI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcFDJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcFID$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcFII$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcFIJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcFJD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcFJI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcFJJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcIDD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcIDI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcIDJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcIID$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcIII$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcIIJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcIJD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcIJI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcIJJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcJDD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcJDI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcJDJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcJID$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcJII$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcJIJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcJJD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcJJI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcJJJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcVDD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcVDI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcVDJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcVID$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcVII$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcVIJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcVJD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcVJI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcVJJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcZDD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcZDI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcZDJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcZID$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcZII$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcZIJ$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcZJD$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcZJI$sp.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2$mcZJJ$sp.java (100%) diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 0f57a22a6e7d..564c8b1e7c33 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -4135,7 +4135,7 @@ class JSCodeGen()(using genCtx: Context) { } private def computeJSNativeLoadSpecOfValDef(sym: Symbol): js.JSNativeLoadSpec = { - atPhase(picklerPhase.next) { + atPhaseBeforeTransforms { computeJSNativeLoadSpecOfInPhase(sym) } } @@ -4144,7 +4144,7 @@ class JSCodeGen()(using genCtx: Context) { if (sym.is(Trait) || sym.hasAnnotation(jsdefn.JSGlobalScopeAnnot)) { None } else { - atPhase(picklerPhase.next) { + atPhaseBeforeTransforms { if (sym.owner.isStaticOwner) Some(computeJSNativeLoadSpecOfInPhase(sym)) else diff --git a/compiler/src/dotty/tools/dotc/core/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala index f140b9c01077..4245ae3ef0ec 100644 --- a/compiler/src/dotty/tools/dotc/core/Annotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala @@ -61,7 +61,7 @@ object Annotations { mySym match { case symFn: (Context ?=> Symbol) @unchecked => mySym = null - mySym = atPhaseNoLater(picklerPhase)(symFn) + mySym = atPhaseBeforeTransforms(symFn) // We should always produce the same annotation tree, no matter when the // annotation is evaluated. Setting the phase to a pre-transformation phase // seems to be enough to ensure this (note that after erasure, `ctx.typer` @@ -79,7 +79,7 @@ object Annotations { myTree match { case treeFn: (Context ?=> Tree) @unchecked => myTree = null - myTree = atPhaseNoLater(picklerPhase)(treeFn) + myTree = atPhaseBeforeTransforms(treeFn) case _ => } myTree.asInstanceOf[Tree] @@ -112,7 +112,7 @@ object Annotations { myTree match { case treeFn: (Context ?=> Tree) @unchecked => myTree = null - myTree = atPhaseNoLater(picklerPhase)(treeFn) + myTree = atPhaseBeforeTransforms(treeFn) case _ => } myTree.asInstanceOf[Tree] diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 83e08ae0cff0..d504809a9a2e 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -76,6 +76,16 @@ object Contexts { inline def atNextPhase[T](inline op: Context ?=> T)(using Context): T = atPhase(ctx.phase.next)(op) + /** Execute `op` at the current phase if it's before the first transform phase, + * otherwise at the last phase before the first transform phase. + * + * Note: this should be used instead of `atPhaseNoLater(ctx.picklerPhase)` + * because the later won't work if the `Pickler` phase is not present (for example, + * when using `QuoteCompiler`). + */ + inline def atPhaseBeforeTransforms[T](inline op: Context ?=> T)(using Context): T = + atPhaseNoLater(firstTransformPhase.prev)(op) + inline def atPhaseNoLater[T](limit: Phase)(inline op: Context ?=> T)(using Context): T = op(using if !limit.exists || ctx.phase <= limit then ctx else ctx.withPhase(limit)) diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index c92077874b80..5c0725e17c4b 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -16,25 +16,26 @@ import Periods._ import typer.{FrontEnd, RefChecks} import typer.ImportInfo.withRootImports import ast.tpd +import scala.annotation.internal.sharable object Phases { inline def phaseOf(id: PhaseId)(using Context): Phase = ctx.base.phases(id) + @sharable object NoPhase extends Phase { + override def exists: Boolean = false + def phaseName: String = "" + def run(using Context): Unit = unsupported("run") + def transform(ref: SingleDenotation)(using Context): SingleDenotation = unsupported("transform") + } + trait PhasesBase { this: ContextBase => // drop NoPhase at beginning def allPhases: Array[Phase] = (if (fusedPhases.nonEmpty) fusedPhases else phases).tail - object NoPhase extends Phase { - override def exists: Boolean = false - def phaseName: String = "" - def run(using Context): Unit = unsupported("run") - def transform(ref: SingleDenotation)(using Context): SingleDenotation = unsupported("transform") - } - object SomePhase extends Phase { def phaseName: String = "" def run(using Context): Unit = unsupported("run") @@ -198,6 +199,7 @@ object Phases { private var mySbtExtractDependenciesPhase: Phase = _ private var myPicklerPhase: Phase = _ private var myPickleQuotesPhase: Phase = _ + private var myFirstTransformPhase: Phase = _ private var myCollectNullableFieldsPhase: Phase = _ private var myRefChecksPhase: Phase = _ private var myPatmatPhase: Phase = _ @@ -217,6 +219,7 @@ object Phases { final def sbtExtractDependenciesPhase: Phase = mySbtExtractDependenciesPhase final def picklerPhase: Phase = myPicklerPhase final def pickleQuotesPhase: Phase = myPickleQuotesPhase + final def firstTransformPhase: Phase = myFirstTransformPhase final def collectNullableFieldsPhase: Phase = myCollectNullableFieldsPhase final def refchecksPhase: Phase = myRefChecksPhase final def patmatPhase: Phase = myPatmatPhase @@ -239,6 +242,7 @@ object Phases { mySbtExtractDependenciesPhase = phaseOfClass(classOf[sbt.ExtractDependencies]) myPicklerPhase = phaseOfClass(classOf[Pickler]) myPickleQuotesPhase = phaseOfClass(classOf[PickleQuotes]) + myFirstTransformPhase = phaseOfClass(classOf[FirstTransform]) myCollectNullableFieldsPhase = phaseOfClass(classOf[CollectNullableFields]) myRefChecksPhase = phaseOfClass(classOf[RefChecks]) myElimRepeatedPhase = phaseOfClass(classOf[ElimRepeated]) @@ -385,10 +389,10 @@ object Phases { exists && id <= that.id final def prev: Phase = - if (id > FirstPhaseId) myBase.phases(start - 1) else myBase.NoPhase + if (id > FirstPhaseId) myBase.phases(start - 1) else NoPhase final def next: Phase = - if (hasNext) myBase.phases(end + 1) else myBase.NoPhase + if (hasNext) myBase.phases(end + 1) else NoPhase final def hasNext: Boolean = start >= FirstPhaseId && end + 1 < myBase.phases.length @@ -403,6 +407,7 @@ object Phases { def sbtExtractDependenciesPhase(using Context): Phase = ctx.base.sbtExtractDependenciesPhase def picklerPhase(using Context): Phase = ctx.base.picklerPhase def pickleQuotesPhase(using Context): Phase = ctx.base.pickleQuotesPhase + def firstTransformPhase(using Context): Phase = ctx.base.firstTransformPhase def refchecksPhase(using Context): Phase = ctx.base.refchecksPhase def elimRepeatedPhase(using Context): Phase = ctx.base.elimRepeatedPhase def extensionMethodsPhase(using Context): Phase = ctx.base.extensionMethodsPhase diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index be8f4aa7c0eb..2bbdc68f9cc2 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -116,7 +116,7 @@ class TreeUnpickler(reader: TastyReader, val owner = ctx.owner val source = ctx.source def complete(denot: SymDenotation)(using Context): Unit = - treeAtAddr(currentAddr) = atPhaseNoLater(picklerPhase) { + treeAtAddr(currentAddr) = atPhaseBeforeTransforms { new TreeReader(reader).readIndexedDef()( using ctx.withOwner(owner).withSource(source)) } @@ -1392,7 +1392,7 @@ class TreeUnpickler(reader: TastyReader, op: TreeReader => Context ?=> T) extends Trees.Lazy[T] { def complete(using Context): T = { pickling.println(i"starting to read at ${reader.reader.currentAddr} with owner $owner") - atPhaseNoLater(picklerPhase) { + atPhaseBeforeTransforms { op(reader)(using ctx .withOwner(owner) .withModeBits(mode) diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 3b2783d64f58..8087396e4084 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -608,7 +608,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas } atReadPos(startCoord(denot).toIndex, () => withMode(Mode.Scala2Unpickling) { - atPhaseNoLater(picklerPhase) { + atPhaseBeforeTransforms { parseToCompletion(denot) } }) diff --git a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala b/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala index 8653dbf7f5fe..2e2e036a0952 100644 --- a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala +++ b/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala @@ -25,7 +25,7 @@ class FunctionalInterfaces extends MiniPhase { def phaseName: String = FunctionalInterfaces.name private val functionName = "JFunction".toTermName - private val functionPackage = "scala.runtime.function.".toTermName + private val functionPackage = "scala.runtime.java8.".toTermName override def transformClosure(tree: Closure)(using Context): Tree = { val cls = tree.tpe.classSymbol.asClass diff --git a/library/src/scala/runtime/function/JFunction0$mcB$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcB$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction0$mcB$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcB$sp.java diff --git a/library/src/scala/runtime/function/JFunction0$mcC$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcC$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction0$mcC$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcC$sp.java diff --git a/library/src/scala/runtime/function/JFunction0$mcD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction0$mcD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcD$sp.java diff --git a/library/src/scala/runtime/function/JFunction0$mcF$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcF$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction0$mcF$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcF$sp.java diff --git a/library/src/scala/runtime/function/JFunction0$mcI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction0$mcI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcI$sp.java diff --git a/library/src/scala/runtime/function/JFunction0$mcJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction0$mcJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction0$mcS$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcS$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction0$mcS$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcS$sp.java diff --git a/library/src/scala/runtime/function/JFunction0$mcV$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcV$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction0$mcV$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcV$sp.java diff --git a/library/src/scala/runtime/function/JFunction0$mcZ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcZ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction0$mcZ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction0$mcZ$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcDD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcDD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcDD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcDD$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcDF$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcDF$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcDF$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcDF$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcDI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcDI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcDI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcDI$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcDJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcDJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcDJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcDJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcFD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcFD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcFD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcFD$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcFF$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcFF$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcFF$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcFF$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcFI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcFI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcFI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcFI$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcFJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcFJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcFJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcFJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcID$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcID$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcID$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcID$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcIF$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcIF$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcIF$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcIF$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcII$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcII$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcII$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcII$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcIJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcIJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcIJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcIJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcJD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcJD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcJD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcJD$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcJF$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcJF$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcJF$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcJF$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcJI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcJI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcJI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcJI$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcJJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcJJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcJJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcJJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcVD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcVD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcVD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcVD$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcVF$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcVF$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcVF$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcVF$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcVI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcVI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcVI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcVI$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcVJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcVJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcVJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcVJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcZD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcZD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcZD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcZD$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcZF$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcZF$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcZF$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcZF$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcZI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcZI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcZI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcZI$sp.java diff --git a/library/src/scala/runtime/function/JFunction1$mcZJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcZJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1$mcZJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1$mcZJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcDDD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDDD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcDDD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDDD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcDDI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDDI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcDDI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDDI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcDDJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDDJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcDDJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDDJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcDID$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDID$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcDID$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDID$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcDII$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDII$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcDII$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDII$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcDIJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDIJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcDIJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDIJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcDJD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDJD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcDJD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDJD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcDJI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDJI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcDJI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDJI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcDJJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDJJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcDJJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcDJJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcFDD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFDD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcFDD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFDD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcFDI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFDI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcFDI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFDI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcFDJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFDJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcFDJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFDJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcFID$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFID$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcFID$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFID$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcFII$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFII$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcFII$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFII$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcFIJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFIJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcFIJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFIJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcFJD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFJD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcFJD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFJD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcFJI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFJI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcFJI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFJI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcFJJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFJJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcFJJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcFJJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcIDD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIDD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcIDD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIDD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcIDI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIDI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcIDI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIDI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcIDJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIDJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcIDJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIDJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcIID$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIID$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcIID$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIID$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcIII$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIII$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcIII$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIII$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcIIJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIIJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcIIJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIIJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcIJD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIJD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcIJD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIJD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcIJI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIJI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcIJI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIJI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcIJJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIJJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcIJJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcIJJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcJDD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJDD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcJDD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJDD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcJDI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJDI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcJDI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJDI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcJDJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJDJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcJDJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJDJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcJID$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJID$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcJID$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJID$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcJII$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJII$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcJII$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJII$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcJIJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJIJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcJIJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJIJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcJJD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJJD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcJJD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJJD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcJJI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJJI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcJJI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJJI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcJJJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJJJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcJJJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcJJJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcVDD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVDD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcVDD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVDD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcVDI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVDI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcVDI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVDI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcVDJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVDJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcVDJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVDJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcVID$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVID$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcVID$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVID$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcVII$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVII$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcVII$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVII$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcVIJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVIJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcVIJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVIJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcVJD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVJD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcVJD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVJD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcVJI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVJI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcVJI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVJI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcVJJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVJJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcVJJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcVJJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcZDD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZDD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcZDD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZDD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcZDI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZDI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcZDI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZDI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcZDJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZDJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcZDJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZDJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcZID$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZID$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcZID$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZID$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcZII$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZII$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcZII$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZII$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcZIJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZIJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcZIJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZIJ$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcZJD$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZJD$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcZJD$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZJD$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcZJI$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZJI$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcZJI$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZJI$sp.java diff --git a/library/src/scala/runtime/function/JFunction2$mcZJJ$sp.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZJJ$sp.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2$mcZJJ$sp.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2$mcZJJ$sp.java From 414956c4f75590ea39f3499ed5a4c8b39743f61a Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sun, 13 Dec 2020 19:24:14 +0100 Subject: [PATCH 3/5] Stop using JFunction{0, 1, 2} Since Scala 2.12, the regular scala.Function{0, 1, 2} are valid SAM types, so these interfaces aren't needed anymore. --- compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala | 1 - .../scala/runtime/function/JFunction0.java | 0 .../scala/runtime/function/JFunction1.java | 0 .../scala/runtime/function/JFunction2.java | 0 library/src/scala/runtime/function/JProcedure0.java | 2 +- library/src/scala/runtime/function/JProcedure1.java | 2 +- library/src/scala/runtime/function/JProcedure2.java | 2 +- 7 files changed, 3 insertions(+), 4 deletions(-) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction0.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction1.java (100%) rename library/{src => src-non-bootstrapped}/scala/runtime/function/JFunction2.java (100%) diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala index 4480adbab448..7d5c25eb4d99 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala @@ -328,7 +328,6 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder { val arity = app.meth.tpe.widenDealias.firstParamTypes.size - env.size val returnsUnit = app.meth.tpe.widenDealias.resultType.classSymbol == defn.UnitClass if (returnsUnit) requiredClass(("scala.runtime.function.JProcedure" + arity)) - else if (arity <= 2) requiredClass(("scala.runtime.function.JFunction" + arity)) else requiredClass(("scala.Function" + arity)) } } diff --git a/library/src/scala/runtime/function/JFunction0.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction0.java similarity index 100% rename from library/src/scala/runtime/function/JFunction0.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction0.java diff --git a/library/src/scala/runtime/function/JFunction1.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction1.java similarity index 100% rename from library/src/scala/runtime/function/JFunction1.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction1.java diff --git a/library/src/scala/runtime/function/JFunction2.java b/library/src-non-bootstrapped/scala/runtime/function/JFunction2.java similarity index 100% rename from library/src/scala/runtime/function/JFunction2.java rename to library/src-non-bootstrapped/scala/runtime/function/JFunction2.java diff --git a/library/src/scala/runtime/function/JProcedure0.java b/library/src/scala/runtime/function/JProcedure0.java index 9c80c759ab63..f0a74ba57e96 100644 --- a/library/src/scala/runtime/function/JProcedure0.java +++ b/library/src/scala/runtime/function/JProcedure0.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure0 extends JFunction0, java.io.Serializable { +public interface JProcedure0 extends scala.Function0, java.io.Serializable { void applyVoid(); default BoxedUnit apply() { diff --git a/library/src/scala/runtime/function/JProcedure1.java b/library/src/scala/runtime/function/JProcedure1.java index eb6ab8f2050d..37252b0bd68b 100644 --- a/library/src/scala/runtime/function/JProcedure1.java +++ b/library/src/scala/runtime/function/JProcedure1.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure1 extends JFunction1, java.io.Serializable { +public interface JProcedure1 extends scala.Function1, java.io.Serializable { void applyVoid(T1 t1); default BoxedUnit apply(T1 t1) { diff --git a/library/src/scala/runtime/function/JProcedure2.java b/library/src/scala/runtime/function/JProcedure2.java index 6ce28658d684..3274140109bf 100644 --- a/library/src/scala/runtime/function/JProcedure2.java +++ b/library/src/scala/runtime/function/JProcedure2.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure2 extends JFunction2, java.io.Serializable { +public interface JProcedure2 extends scala.Function2, java.io.Serializable { void applyVoid(T1 t1, T2 t2); default BoxedUnit apply(T1 t1, T2 t2) { From 384a0aa02a9604105b7d6d34ae744e28647986f7 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Wed, 23 Dec 2020 17:07:13 +0100 Subject: [PATCH 4/5] Refactor closure adaptation As described in details in `Erasure#adaptClosure`, in some situation we need to perform some transformation to make the closure implementation method type match the type of the single abstract method of the functional interface this closure implements, previously the responsability for doing this was split in three places: - The FunctionalInterfaces phase was setting the functional interface of specializable FunctionN instances to the corresponding specialized JFunction*mc* interface - The backend set the functional interface of a Unit-returning FunctionN to JProcedureN - And `adaptClosure` generated a bridge method in all other situations where some adaptation was needed. This commit centralizes all of this logic in `adaptClosure` which allows us to remove one phase, and in general makes it easier to follow what's going on. --- .../tools/backend/jvm/BCodeBodyBuilder.scala | 17 +- compiler/src/dotty/tools/dotc/Compiler.scala | 1 - .../dotty/tools/dotc/core/Definitions.scala | 7 +- .../src/dotty/tools/dotc/core/NameOps.scala | 4 +- .../src/dotty/tools/dotc/core/StdNames.scala | 3 + .../dotty/tools/dotc/transform/Erasure.scala | 192 ++++++++++-------- .../dotc/transform/FunctionalInterfaces.scala | 49 ----- 7 files changed, 127 insertions(+), 146 deletions(-) delete mode 100644 compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala index 7d5c25eb4d99..2b21762fba72 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala @@ -318,19 +318,10 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder { abort(s"Unexpected New(${tpt.tpe.showSummary()}/$tpt) reached GenBCode.\n" + " Call was genLoad" + ((tree, expectedType))) - case app: Closure => - val env: List[Tree] = app.env - val call: Tree = app.meth - val functionalInterface: Symbol = { - val t = app.tpt.tpe.typeSymbol - if (t.exists) t - else { - val arity = app.meth.tpe.widenDealias.firstParamTypes.size - env.size - val returnsUnit = app.meth.tpe.widenDealias.resultType.classSymbol == defn.UnitClass - if (returnsUnit) requiredClass(("scala.runtime.function.JProcedure" + arity)) - else requiredClass(("scala.Function" + arity)) - } - } + case t @ Closure(env, call, tpt) => + val functionalInterface: Symbol = + if !tpt.isEmpty then tpt.tpe.classSymbol + else t.tpe.classSymbol val (fun, args) = call match { case Apply(fun, args) => (fun, args) case t @ DesugaredSelect(_, _) => (t, Nil) // TODO: use Select diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index 6dc8e33402a4..2d48c7a98d94 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -111,7 +111,6 @@ class Compiler { new CapturedVars) :: // Represent vars captured by closures as heap objects List(new Constructors, // Collect initialization code in primary constructors // Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it - new FunctionalInterfaces, // Rewrites closures to implement @specialized types of Functions. new Instrumentation) :: // Count calls and allocations under -Yinstrument List(new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments // Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index a9da2c31c176..cca01dd32a48 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1464,7 +1464,12 @@ class Definitions { new PerRun(Function2SpecializedReturnTypes.map(_.symbol)) def isSpecializableFunction(cls: ClassSymbol, paramTypes: List[Type], retType: Type)(using Context): Boolean = - paramTypes.length <= 2 && cls.derivesFrom(FunctionClass(paramTypes.length)) && (paramTypes match { + paramTypes.length <= 2 && cls.derivesFrom(FunctionClass(paramTypes.length)) + && isSpecializableFunctionSAM(paramTypes, retType) + + /** If the Single Abstract Method of a Function class has this type, is it specializable? */ + def isSpecializableFunctionSAM(paramTypes: List[Type], retType: Type)(using Context): Boolean = + paramTypes.length <= 2 && (paramTypes match { case Nil => Function0SpecializedReturnClasses().contains(retType.typeSymbol) case List(paramType0) => diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index b9d45385f389..32900e9e66c9 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -300,7 +300,7 @@ object NameOps { * * `<...>` */ - def specializedFunction(ret: Type, args: List[Type])(using Context): Name = + def specializedFunction(ret: Type, args: List[Type])(using Context): N = val sb = new StringBuilder sb.append(name.toString) sb.append(nme.specializedTypeNames.prefix.toString) @@ -308,7 +308,7 @@ object NameOps { sb.append(defn.typeTag(ret).toString) args.foreach { arg => sb.append(defn.typeTag(arg)) } sb.append(nme.specializedTypeNames.suffix) - termName(sb.toString) + likeSpacedN(termName(sb.toString)) /** If name length exceeds allowable limit, replace part of it by hash */ def compactified(using Context): TermName = termName(compactify(name.toString)) diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 2a4c6a500f07..98978fec6778 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -830,6 +830,9 @@ object StdNames { final val Conforms: TypeName = encode("<:<") final val Uninstantiated: TypeName = "?$" + + val JFunctionPrefix: Seq[TypeName] = (0 to 2).map(i => s"scala.runtime.java8.JFunction${i}") + val JProcedure: Seq[TypeName] = (0 to 22).map(i => s"scala.runtime.function.JProcedure${i}") } abstract class JavaNames[N <: Name] extends DefinedNames[N] { diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 9b67c8cbf21a..28417bcf5930 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -376,99 +376,131 @@ object Erasure { * * val f: Function1[Int, Any] = x => ... * - * results in the creation of a closure and a method in the typer: + * results in the creation of a closure and an implementation method in the typer: * * def $anonfun(x: Int): Any = ... * val f: Function1[Int, Any] = closure($anonfun) * - * Notice that `$anonfun` takes a primitive as argument, but the single abstract method + * Notice that `$anonfun` takes a primitive as argument, but the SAM (Single Abstract Method) * of `Function1` after erasure is: * * def apply(x: Object): Object * - * which takes a reference as argument. Hence, some form of adaptation is required. + * which takes a reference as argument. Hence, some form of adaptation is + * required. The most reliable way to do this adaptation is to replace the + * closure implementation method by a bridge method that forwards to the + * original method with appropriate boxing/unboxing. For our example above, + * this would be: * - * If we do nothing, the LambdaMetaFactory bootstrap method will - * automatically do the adaptation. Unfortunately, the result does not - * implement the expected Scala semantics: null should be "unboxed" to - * the default value of the value class, but LMF will throw a - * NullPointerException instead. LMF is also not capable of doing - * adaptation for derived value classes. + * def $anonfun$adapted(x: Object): Object = $anonfun(BoxesRunTime.unboxToInt(x)) + * val f: Function1 = closure($anonfun$adapted) * - * Thus, we need to replace the closure method by a bridge method that - * forwards to the original closure method with appropriate - * boxing/unboxing. For our example above, this would be: - * - * def $anonfun1(x: Object): Object = $anonfun(BoxesRunTime.unboxToInt(x)) - * val f: Function1 = closure($anonfun1) - * - * In general a bridge is needed when, after Erasure, one of the - * parameter type or the result type of the closure method has a - * different type, and we cannot rely on auto-adaptation. - * - * Auto-adaptation works in the following cases: - * - If the SAM is replaced by JFunction*mc* in - * [[FunctionalInterfaces]], no bridge is needed: the SAM contains - * default methods to handle adaptation. - * - If a result type of the closure method is a primitive value type - * different from Unit, we can rely on the auto-adaptation done by - * LMF (because it only needs to box, not unbox, so no special - * handling of null is required). - * - If the SAM is replaced by JProcedure* in - * [[DottyBackendInterface]] (this only happens when no explicit SAM - * type is given), no bridge is needed to box a Unit result type: - * the SAM contains a default method to handle that. + * But in some situations we can avoid generating this bridge, either + * because the runtime can perform auto-adaptation, or because we can + * replace the closure functional interface by a specialized sub-interface, + * see comments in this method for details. * * See test cases lambda-*.scala and t8017/ for concrete examples. */ - def adaptClosure(tree: tpd.Closure)(using Context): Tree = { - val implClosure @ Closure(_, meth, _) = tree - - implClosure.tpe match { - case SAMType(sam) => - val implType = meth.tpe.widen.asInstanceOf[MethodType] - - val implParamTypes = implType.paramInfos - val List(samParamTypes) = sam.paramInfoss - val implResultType = implType.resultType - val samResultType = sam.resultType - - if (!defn.isSpecializableFunction(implClosure.tpe.classSymbol.asClass, implParamTypes, implResultType)) { - def autoAdaptedParam(tp: Type) = !tp.isErasedValueType && !tp.isPrimitiveValueType - val explicitSAMType = implClosure.tpt.tpe.exists - def autoAdaptedResult(tp: Type) = !tp.isErasedValueType && - (!explicitSAMType || tp.typeSymbol != defn.UnitClass) - def sameSymbol(tp1: Type, tp2: Type) = tp1.typeSymbol == tp2.typeSymbol - - val paramAdaptationNeeded = - implParamTypes.lazyZip(samParamTypes).exists((implType, samType) => - !sameSymbol(implType, samType) && !autoAdaptedParam(implType)) - val resultAdaptationNeeded = - !sameSymbol(implResultType, samResultType) && !autoAdaptedResult(implResultType) - - if (paramAdaptationNeeded || resultAdaptationNeeded) { - val bridgeType = - if (paramAdaptationNeeded) - if (resultAdaptationNeeded) sam - else implType.derivedLambdaType(paramInfos = samParamTypes) - else implType.derivedLambdaType(resType = samResultType) - val bridge = newSymbol(ctx.owner, AdaptedClosureName(meth.symbol.name.asTermName), Flags.Synthetic | Flags.Method, bridgeType) - Closure(bridge, bridgeParamss => - inContext(ctx.withOwner(bridge)) { - val List(bridgeParams) = bridgeParamss - assert(ctx.typer.isInstanceOf[Erasure.Typer]) - val rhs = Apply(meth, bridgeParams.lazyZip(implParamTypes).map(ctx.typer.adapt(_, _))) - ctx.typer.adapt(rhs, bridgeType.resultType) - }, - targetType = implClosure.tpt.tpe) - } - else implClosure - } - else implClosure - case _ => - implClosure - } - } + def adaptClosure(tree: tpd.Closure)(using Context): Tree = + val Closure(env, meth, tpt) = tree + assert(env.isEmpty, tree) + + // The type of the lambda expression + val lambdaType = tree.tpe + // The interface containing the SAM that this closure should implement + val functionalInterface = tpt.tpe + // A lack of an explicit functional interface means we're implementing a scala.FunctionN + val isFunction = !functionalInterface.exists + // The actual type of the implementation method + val implType = meth.tpe.widen.asInstanceOf[MethodType] + val implParamTypes = implType.paramInfos + val implResultType = implType.resultType + val implReturnsUnit = implResultType.classSymbol eq defn.UnitClass + // The SAM that this closure should implement + val SAMType(sam) = lambdaType: @unchecked + val samParamTypes = sam.paramInfos + val samResultType = sam.resultType + + /** Can the implementation parameter type `tp` be auto-adapted to a different + * parameter type in the SAM? + * + * For derived value classes, we always need to do the bridging manually. + * For primitives, we cannot rely on auto-adaptation on the JVM because + * the Scala spec requires null to be "unboxed" to the default value of + * the value class, but the adaptation performed by LambdaMetaFactory + * will throw a `NullPointerException` instead. See `lambda-null.scala` + * for test cases. + * + * @see [LambdaMetaFactory](https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html) + */ + def autoAdaptedParam(tp: Type) = + !tp.isErasedValueType && !tp.isPrimitiveValueType + + /** Can the implementation result type be auto-adapted to a different result + * type in the SAM? + * + * For derived value classes, it's the same story as for parameters. + * For non-Unit primitives, we can actually rely on the `LambdaMetaFactory` + * adaptation, because it only needs to box, not unbox, so no special + * handling of null is required. + */ + def autoAdaptedResult = + !implResultType.isErasedValueType && !implReturnsUnit + + def sameClass(tp1: Type, tp2: Type) = tp1.classSymbol == tp2.classSymbol + + val paramAdaptationNeeded = + implParamTypes.lazyZip(samParamTypes).exists((implType, samType) => + !sameClass(implType, samType) && !autoAdaptedParam(implType)) + val resultAdaptationNeeded = + !sameClass(implResultType, samResultType) && !autoAdaptedResult + + if paramAdaptationNeeded || resultAdaptationNeeded then + // Instead of instantiating `scala.FunctionN`, see if we can instantiate + // a specialized sub-interface where the SAM type matches the + // implementation method type, thus avoiding the need for bridging. + // This optimization is skipped when using Scala.js because its backend + // does not support closures using custom functional interfaces. + if isFunction && !ctx.settings.scalajs.value then + val arity = implParamTypes.length + val specializedFunctionalInterface = + if defn.isSpecializableFunctionSAM(implParamTypes, implResultType) then + // Using these subclasses is critical to avoid boxing since their + // SAM is a specialized method `apply$mc*$sp` whose default + // implementation in FunctionN boxes. + tpnme.JFunctionPrefix(arity).specializedFunction(implResultType, implParamTypes) + else if !paramAdaptationNeeded && implReturnsUnit then + // Here, there is no actual boxing to avoid so we could get by + // without JProcedureN, but Unit-returning functions are very + // common so it seems worth it to not generate bridges for them. + tpnme.JProcedure(arity) + else + EmptyTypeName + if !specializedFunctionalInterface.isEmpty then + return cpy.Closure(tree)(tpt = TypeTree(requiredClass(specializedFunctionalInterface).typeRef)) + + // Otherwise, generate a new closure implemented with a bridge. + val bridgeType = + if paramAdaptationNeeded then + if resultAdaptationNeeded then + sam + else + implType.derivedLambdaType(paramInfos = samParamTypes) + else + implType.derivedLambdaType(resType = samResultType) + val bridge = newSymbol(ctx.owner, AdaptedClosureName(meth.symbol.name.asTermName), Flags.Synthetic | Flags.Method, bridgeType) + Closure(bridge, bridgeParamss => + inContext(ctx.withOwner(bridge)) { + val List(bridgeParams) = bridgeParamss + assert(ctx.typer.isInstanceOf[Erasure.Typer]) + val rhs = Apply(meth, bridgeParams.lazyZip(implParamTypes).map(ctx.typer.adapt(_, _))) + ctx.typer.adapt(rhs, bridgeType.resultType) + }, + targetType = functionalInterface).withSpan(tree.span) + else + tree + end adaptClosure /** Eta expand given `tree` that has the given method type `mt`, so that * it conforms to erased result type `pt`. diff --git a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala b/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala deleted file mode 100644 index 2e2e036a0952..000000000000 --- a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala +++ /dev/null @@ -1,49 +0,0 @@ -package dotty.tools.dotc -package transform - -import core._ -import MegaPhase._ -import Names._ -import Symbols._ -import Contexts._ -import Decorators._ -import NameOps._ -import Phases._ -import dotty.tools.dotc.ast.tpd - - -object FunctionalInterfaces { - val name: String = "functionalInterfaces" -} - -/** - * Rewires closures to implement more specific types of Functions. - */ -class FunctionalInterfaces extends MiniPhase { - import tpd._ - - def phaseName: String = FunctionalInterfaces.name - - private val functionName = "JFunction".toTermName - private val functionPackage = "scala.runtime.java8.".toTermName - - override def transformClosure(tree: Closure)(using Context): Tree = { - val cls = tree.tpe.classSymbol.asClass - - val implType = tree.meth.tpe.widen - val List(implParamTypes) = implType.paramInfoss - val implResultType = implType.resultType - - if (defn.isSpecializableFunction(cls, implParamTypes, implResultType) && - !ctx.settings.scalajs.value) { // never do anything for Scala.js, but do this test as late as possible not to slow down Scala/JVM - val names = atPhase(erasurePhase) { cls.typeParams.map(_.name) } - val interfaceName = (functionName ++ implParamTypes.length.toString).specializedFor(implParamTypes ::: implResultType :: Nil, names, Nil, Nil) - - // symbols loaded from classpath aren't defined in periods earlier than when they where loaded - val interface = atPhase(typerPhase)(requiredClass(functionPackage ++ interfaceName)) - val tpt = tpd.TypeTree(interface.asType.appliedRef) - tpd.Closure(tree.env, tree.meth, tpt) - } - else tree - } -} From 58064cfaaa1f1f19208fb83953d2a8e8d0f48774 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 26 Dec 2020 17:03:50 +0100 Subject: [PATCH 5/5] docs: update phase list --- docs/docs/internals/overall-structure.md | 48 +++++++++++++----------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/docs/docs/internals/overall-structure.md b/docs/docs/internals/overall-structure.md index 94f14062a35d..874155589116 100644 --- a/docs/docs/internals/overall-structure.md +++ b/docs/docs/internals/overall-structure.md @@ -99,10 +99,11 @@ phases. The current list of phases is specified in class [Compiler] as follows: protected def frontendPhases: List[List[Phase]] = List(new FrontEnd) :: // Compiler frontend: scanner, parser, namer, typer List(new YCheckPositions) :: // YCheck positions - List(new Staging) :: // Check PCP, heal quoted types and expand macros List(new sbt.ExtractDependencies) :: // Sends information on classes' dependencies to sbt via callbacks List(new semanticdb.ExtractSemanticDB) :: // Extract info into .semanticdb files List(new PostTyper) :: // Additional checks and cleanups after type checking + List(new sjs.PrepJSInterop) :: // Additional checks and transformations for Scala.js (Scala.js only) + List(new Staging) :: // Check PCP, heal quoted types and expand macros List(new sbt.ExtractAPI) :: // Sends a representation of the API of classes to sbt via callbacks List(new SetRootTree) :: // Set the `rootTreeOrProvider` on class symbols Nil @@ -119,44 +120,51 @@ phases. The current list of phases is specified in class [Compiler] as follows: new CheckReentrant, // Internal use only: Check that compiled program has no data races involving global vars new ElimPackagePrefixes, // Eliminate references to package prefixes in Select nodes new CookComments, // Cook the comments: expand variables, doc, etc. - new CompleteJavaEnums) :: // Fill in constructors for Java enums - List(new CheckStatic, // Check restrictions that apply to @static members - new ElimRepeated, // Rewrite vararg parameters and arguments + new CheckStatic, // Check restrictions that apply to @static members + new BetaReduce, // Reduce closure applications + new init.Checker) :: // Check initialization of objects + List(new ElimRepeated, // Rewrite vararg parameters and arguments new ExpandSAMs, // Expand single abstract method closures to anonymous classes new ProtectedAccessors, // Add accessors for protected members new ExtensionMethods, // Expand methods of value classes with extension methods - new CacheAliasImplicits, // Cache RHS of parameterless alias implicits - new ShortcutImplicits, // Allow implicit functions without creating closures + new UncacheGivenAliases, // Avoid caching RHS of simple parameterless given aliases new ByNameClosures, // Expand arguments to by-name parameters to closures new HoistSuperArgs, // Hoist complex arguments of supercalls to enclosing scope - new ClassOf, // Expand `Predef.classOf` calls. + new SpecializeApplyMethods, // Adds specialized methods to FunctionN new RefChecks) :: // Various checks mostly related to abstract members and overriding List(new ElimOpaque, // Turn opaque into normal aliases new TryCatchPatterns, // Compile cases in try/catch new PatternMatcher, // Compile pattern matches + new sjs.ExplicitJSClasses, // Make all JS classes explicit (Scala.js only) new ExplicitOuter, // Add accessors to outer classes from nested ones. new ExplicitSelf, // Make references to non-trivial self types explicit as casts - new StringInterpolatorOpt, // Optimizes raw and s string interpolators by rewriting them to string concatentations - new CrossCastAnd) :: // Normalize selections involving intersection types. + new ElimByName, // Expand by-name parameter references + new StringInterpolatorOpt) :: // Optimizes raw and s string interpolators by rewriting them to string concatentations List(new PruneErasedDefs, // Drop erased definitions from scopes and simplify erased expressions + new InlinePatterns, // Remove placeholders of inlined patterns new VCInlineMethods, // Inlines calls to value class methods new SeqLiterals, // Express vararg arguments as arrays new InterceptedMethods, // Special handling of `==`, `|=`, `getClass` methods new Getters, // Replace non-private vals and vars with getter defs (fields are added later) - new ElimByName, // Expand by-name parameter references + new SpecializeFunctions, // Specialized Function{0,1,2} by replacing super with specialized super + new LiftTry, // Put try expressions that might execute on non-empty stacks into their own methods new CollectNullableFields, // Collect fields that can be nulled out after use in lazy initialization new ElimOuterSelect, // Expand outer selections - new AugmentScala2Traits, // Augments Scala2 traits so that super accessors are made non-private new ResolveSuper, // Implement super accessors new FunctionXXLForwarders, // Add forwarders for FunctionXXL apply method + new ParamForwarding, // Add forwarders for aliases of superclass parameters new TupleOptimizations, // Optimize generic operations on tuples + new LetOverApply, // Lift blocks from receivers of applications new ArrayConstructors) :: // Intercept creation of (non-generic) arrays and intrinsify. List(new Erasure) :: // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements. List(new ElimErasedValueType, // Expand erased value types to their underlying implmementation types + new PureStats, // Remove pure stats from blocks new VCElideAllocations, // Peep-hole optimization to eliminate unnecessary value class allocations new ArrayApply, // Optimize `scala.Array.apply([....])` and `scala.Array.apply(..., [....])` into `[...]` + new sjs.AddLocalJSFakeNews, // Adds fake new invocations to local JS classes in calls to `createLocalJSClass` new ElimPolyFunction, // Rewrite PolyFunction subclasses to FunctionN subclasses new TailRec, // Rewrite tail recursion to loops + new CompleteJavaEnums, // Fill in constructors for Java enums new Mixin, // Expand trait fields and trait initializers new LazyVals, // Expand lazy vals new Memoize, // Add private fields to getters and setters @@ -164,14 +172,13 @@ phases. The current list of phases is specified in class [Compiler] as follows: new CapturedVars) :: // Represent vars captured by closures as heap objects List(new Constructors, // Collect initialization code in primary constructors // Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it - new FunctionalInterfaces, // Rewrites closures to implement @specialized types of Functions. - new Instrumentation, // Count closure allocations under -Yinstrument-closures - new GetClass, // Rewrites getClass calls on primitive types. - new LiftTry) :: // Put try expressions that might execute on non-empty stacks into their own methods their implementations + new Instrumentation) :: // Count calls and allocations under -Yinstrument List(new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments - // Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here - new ElimStaticThis) :: // Replace `this` references to static objects by global identifiers - List(new Flatten, // Lift all inner classes to package scope + // Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here + new ElimStaticThis, // Replace `this` references to static objects by global identifiers + new CountOuterAccesses) :: // Identify outer accessors that can be dropped + List(new DropOuterAccessors, // Drop unused outer accessors + new Flatten, // Lift all inner classes to package scope new RenameLifted, // Renames lifted classes to local numbering scheme new TransformWildcards, // Replace wildcards with default values new MoveStatics, // Move static methods from companion to the class itself @@ -179,14 +186,13 @@ phases. The current list of phases is specified in class [Compiler] as follows: new RestoreScopes, // Repair scopes rendered invalid by moving definitions in prior phases of the group new SelectStatic, // get rid of selects that would be compiled into GetStatic new sjs.JUnitBootstrappers, // Generate JUnit-specific bootstrapper classes for Scala.js (not enabled by default) - new CollectEntryPoints, // Find classes with main methods new CollectSuperCalls) :: // Find classes that are called with super Nil /** Generate the output of the compilation */ protected def backendPhases: List[List[Phase]] = - List(new sjs.GenSJSIR) :: // Generate .sjsir files for Scala.js (not enabled by default) - List(new GenBCode) :: // Generate JVM bytecode + List(new backend.sjs.GenSJSIR) :: // Generate .sjsir files for Scala.js (not enabled by default) + List(new GenBCode) :: // Generate JVM bytecode Nil ```