Skip to content

Commit d8a6056

Browse files
authored
Merge pull request #10920 from dotty-staging/jfunction-cleanup-4
2 parents 2a32d6a + 58064cf commit d8a6056

File tree

108 files changed

+190
-189
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+190
-189
lines changed

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

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -318,20 +318,10 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
318318
abort(s"Unexpected New(${tpt.tpe.showSummary()}/$tpt) reached GenBCode.\n" +
319319
" Call was genLoad" + ((tree, expectedType)))
320320

321-
case app: Closure =>
322-
val env: List[Tree] = app.env
323-
val call: Tree = app.meth
324-
val functionalInterface: Symbol = {
325-
val t = app.tpt.tpe.typeSymbol
326-
if (t.exists) t
327-
else {
328-
val arity = app.meth.tpe.widenDealias.firstParamTypes.size - env.size
329-
val returnsUnit = app.meth.tpe.widenDealias.resultType.classSymbol == defn.UnitClass
330-
if (returnsUnit) requiredClass(("scala.runtime.function.JProcedure" + arity))
331-
else if (arity <= 2) requiredClass(("scala.runtime.function.JFunction" + arity))
332-
else requiredClass(("scala.Function" + arity))
333-
}
334-
}
321+
case t @ Closure(env, call, tpt) =>
322+
val functionalInterface: Symbol =
323+
if !tpt.isEmpty then tpt.tpe.classSymbol
324+
else t.tpe.classSymbol
335325
val (fun, args) = call match {
336326
case Apply(fun, args) => (fun, args)
337327
case t @ DesugaredSelect(_, _) => (t, Nil) // TODO: use Select

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4135,7 +4135,7 @@ class JSCodeGen()(using genCtx: Context) {
41354135
}
41364136

41374137
private def computeJSNativeLoadSpecOfValDef(sym: Symbol): js.JSNativeLoadSpec = {
4138-
atPhase(picklerPhase.next) {
4138+
atPhaseBeforeTransforms {
41394139
computeJSNativeLoadSpecOfInPhase(sym)
41404140
}
41414141
}
@@ -4144,7 +4144,7 @@ class JSCodeGen()(using genCtx: Context) {
41444144
if (sym.is(Trait) || sym.hasAnnotation(jsdefn.JSGlobalScopeAnnot)) {
41454145
None
41464146
} else {
4147-
atPhase(picklerPhase.next) {
4147+
atPhaseBeforeTransforms {
41484148
if (sym.owner.isStaticOwner)
41494149
Some(computeJSNativeLoadSpecOfInPhase(sym))
41504150
else

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ class Compiler {
111111
new CapturedVars) :: // Represent vars captured by closures as heap objects
112112
List(new Constructors, // Collect initialization code in primary constructors
113113
// Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it
114-
new FunctionalInterfaces, // Rewrites closures to implement @specialized types of Functions.
115114
new Instrumentation) :: // Count calls and allocations under -Yinstrument
116115
List(new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments
117116
// Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here

compiler/src/dotty/tools/dotc/core/Annotations.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ object Annotations {
6161
mySym match {
6262
case symFn: (Context ?=> Symbol) @unchecked =>
6363
mySym = null
64-
mySym = atPhaseNoLater(picklerPhase)(symFn)
64+
mySym = atPhaseBeforeTransforms(symFn)
6565
// We should always produce the same annotation tree, no matter when the
6666
// annotation is evaluated. Setting the phase to a pre-transformation phase
6767
// seems to be enough to ensure this (note that after erasure, `ctx.typer`
@@ -79,7 +79,7 @@ object Annotations {
7979
myTree match {
8080
case treeFn: (Context ?=> Tree) @unchecked =>
8181
myTree = null
82-
myTree = atPhaseNoLater(picklerPhase)(treeFn)
82+
myTree = atPhaseBeforeTransforms(treeFn)
8383
case _ =>
8484
}
8585
myTree.asInstanceOf[Tree]
@@ -112,7 +112,7 @@ object Annotations {
112112
myTree match {
113113
case treeFn: (Context ?=> Tree) @unchecked =>
114114
myTree = null
115-
myTree = atPhaseNoLater(picklerPhase)(treeFn)
115+
myTree = atPhaseBeforeTransforms(treeFn)
116116
case _ =>
117117
}
118118
myTree.asInstanceOf[Tree]

compiler/src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ object Contexts {
7676
inline def atNextPhase[T](inline op: Context ?=> T)(using Context): T =
7777
atPhase(ctx.phase.next)(op)
7878

79+
/** Execute `op` at the current phase if it's before the first transform phase,
80+
* otherwise at the last phase before the first transform phase.
81+
*
82+
* Note: this should be used instead of `atPhaseNoLater(ctx.picklerPhase)`
83+
* because the later won't work if the `Pickler` phase is not present (for example,
84+
* when using `QuoteCompiler`).
85+
*/
86+
inline def atPhaseBeforeTransforms[T](inline op: Context ?=> T)(using Context): T =
87+
atPhaseNoLater(firstTransformPhase.prev)(op)
88+
7989
inline def atPhaseNoLater[T](limit: Phase)(inline op: Context ?=> T)(using Context): T =
8090
op(using if !limit.exists || ctx.phase <= limit then ctx else ctx.withPhase(limit))
8191

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1464,7 +1464,12 @@ class Definitions {
14641464
new PerRun(Function2SpecializedReturnTypes.map(_.symbol))
14651465

14661466
def isSpecializableFunction(cls: ClassSymbol, paramTypes: List[Type], retType: Type)(using Context): Boolean =
1467-
paramTypes.length <= 2 && cls.derivesFrom(FunctionClass(paramTypes.length)) && (paramTypes match {
1467+
paramTypes.length <= 2 && cls.derivesFrom(FunctionClass(paramTypes.length))
1468+
&& isSpecializableFunctionSAM(paramTypes, retType)
1469+
1470+
/** If the Single Abstract Method of a Function class has this type, is it specializable? */
1471+
def isSpecializableFunctionSAM(paramTypes: List[Type], retType: Type)(using Context): Boolean =
1472+
paramTypes.length <= 2 && (paramTypes match {
14681473
case Nil =>
14691474
Function0SpecializedReturnClasses().contains(retType.typeSymbol)
14701475
case List(paramType0) =>

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ object Denotations {
585585
try info.signature
586586
catch { // !!! DEBUG
587587
case scala.util.control.NonFatal(ex) =>
588-
report.echo(s"cannot take signature of ${info.show}")
588+
report.echo(s"cannot take signature of $info")
589589
throw ex
590590
}
591591
case _ => Signature.NotAMethod

compiler/src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,15 +300,15 @@ object NameOps {
300300
*
301301
* `<return type><first type><second type><...>`
302302
*/
303-
def specializedFunction(ret: Type, args: List[Type])(using Context): Name =
303+
def specializedFunction(ret: Type, args: List[Type])(using Context): N =
304304
val sb = new StringBuilder
305305
sb.append(name.toString)
306306
sb.append(nme.specializedTypeNames.prefix.toString)
307307
sb.append(nme.specializedTypeNames.separator)
308308
sb.append(defn.typeTag(ret).toString)
309309
args.foreach { arg => sb.append(defn.typeTag(arg)) }
310310
sb.append(nme.specializedTypeNames.suffix)
311-
termName(sb.toString)
311+
likeSpacedN(termName(sb.toString))
312312

313313
/** If name length exceeds allowable limit, replace part of it by hash */
314314
def compactified(using Context): TermName = termName(compactify(name.toString))

compiler/src/dotty/tools/dotc/core/Phases.scala

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,26 @@ import Periods._
1616
import typer.{FrontEnd, RefChecks}
1717
import typer.ImportInfo.withRootImports
1818
import ast.tpd
19+
import scala.annotation.internal.sharable
1920

2021
object Phases {
2122

2223
inline def phaseOf(id: PhaseId)(using Context): Phase =
2324
ctx.base.phases(id)
2425

26+
@sharable object NoPhase extends Phase {
27+
override def exists: Boolean = false
28+
def phaseName: String = "<no phase>"
29+
def run(using Context): Unit = unsupported("run")
30+
def transform(ref: SingleDenotation)(using Context): SingleDenotation = unsupported("transform")
31+
}
32+
2533
trait PhasesBase {
2634
this: ContextBase =>
2735

2836
// drop NoPhase at beginning
2937
def allPhases: Array[Phase] = (if (fusedPhases.nonEmpty) fusedPhases else phases).tail
3038

31-
object NoPhase extends Phase {
32-
override def exists: Boolean = false
33-
def phaseName: String = "<no phase>"
34-
def run(using Context): Unit = unsupported("run")
35-
def transform(ref: SingleDenotation)(using Context): SingleDenotation = unsupported("transform")
36-
}
37-
3839
object SomePhase extends Phase {
3940
def phaseName: String = "<some phase>"
4041
def run(using Context): Unit = unsupported("run")
@@ -198,6 +199,7 @@ object Phases {
198199
private var mySbtExtractDependenciesPhase: Phase = _
199200
private var myPicklerPhase: Phase = _
200201
private var myPickleQuotesPhase: Phase = _
202+
private var myFirstTransformPhase: Phase = _
201203
private var myCollectNullableFieldsPhase: Phase = _
202204
private var myRefChecksPhase: Phase = _
203205
private var myPatmatPhase: Phase = _
@@ -217,6 +219,7 @@ object Phases {
217219
final def sbtExtractDependenciesPhase: Phase = mySbtExtractDependenciesPhase
218220
final def picklerPhase: Phase = myPicklerPhase
219221
final def pickleQuotesPhase: Phase = myPickleQuotesPhase
222+
final def firstTransformPhase: Phase = myFirstTransformPhase
220223
final def collectNullableFieldsPhase: Phase = myCollectNullableFieldsPhase
221224
final def refchecksPhase: Phase = myRefChecksPhase
222225
final def patmatPhase: Phase = myPatmatPhase
@@ -239,6 +242,7 @@ object Phases {
239242
mySbtExtractDependenciesPhase = phaseOfClass(classOf[sbt.ExtractDependencies])
240243
myPicklerPhase = phaseOfClass(classOf[Pickler])
241244
myPickleQuotesPhase = phaseOfClass(classOf[PickleQuotes])
245+
myFirstTransformPhase = phaseOfClass(classOf[FirstTransform])
242246
myCollectNullableFieldsPhase = phaseOfClass(classOf[CollectNullableFields])
243247
myRefChecksPhase = phaseOfClass(classOf[RefChecks])
244248
myElimRepeatedPhase = phaseOfClass(classOf[ElimRepeated])
@@ -385,10 +389,10 @@ object Phases {
385389
exists && id <= that.id
386390

387391
final def prev: Phase =
388-
if (id > FirstPhaseId) myBase.phases(start - 1) else myBase.NoPhase
392+
if (id > FirstPhaseId) myBase.phases(start - 1) else NoPhase
389393

390394
final def next: Phase =
391-
if (hasNext) myBase.phases(end + 1) else myBase.NoPhase
395+
if (hasNext) myBase.phases(end + 1) else NoPhase
392396

393397
final def hasNext: Boolean = start >= FirstPhaseId && end + 1 < myBase.phases.length
394398

@@ -403,6 +407,7 @@ object Phases {
403407
def sbtExtractDependenciesPhase(using Context): Phase = ctx.base.sbtExtractDependenciesPhase
404408
def picklerPhase(using Context): Phase = ctx.base.picklerPhase
405409
def pickleQuotesPhase(using Context): Phase = ctx.base.pickleQuotesPhase
410+
def firstTransformPhase(using Context): Phase = ctx.base.firstTransformPhase
406411
def refchecksPhase(using Context): Phase = ctx.base.refchecksPhase
407412
def elimRepeatedPhase(using Context): Phase = ctx.base.elimRepeatedPhase
408413
def extensionMethodsPhase(using Context): Phase = ctx.base.extensionMethodsPhase

compiler/src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,9 @@ object StdNames {
830830
final val Conforms: TypeName = encode("<:<")
831831

832832
final val Uninstantiated: TypeName = "?$"
833+
834+
val JFunctionPrefix: Seq[TypeName] = (0 to 2).map(i => s"scala.runtime.java8.JFunction${i}")
835+
val JProcedure: Seq[TypeName] = (0 to 22).map(i => s"scala.runtime.function.JProcedure${i}")
833836
}
834837

835838
abstract class JavaNames[N <: Name] extends DefinedNames[N] {

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class TreeUnpickler(reader: TastyReader,
116116
val owner = ctx.owner
117117
val source = ctx.source
118118
def complete(denot: SymDenotation)(using Context): Unit =
119-
treeAtAddr(currentAddr) = atPhaseNoLater(picklerPhase) {
119+
treeAtAddr(currentAddr) = atPhaseBeforeTransforms {
120120
new TreeReader(reader).readIndexedDef()(
121121
using ctx.withOwner(owner).withSource(source))
122122
}
@@ -1392,7 +1392,7 @@ class TreeUnpickler(reader: TastyReader,
13921392
op: TreeReader => Context ?=> T) extends Trees.Lazy[T] {
13931393
def complete(using Context): T = {
13941394
pickling.println(i"starting to read at ${reader.reader.currentAddr} with owner $owner")
1395-
atPhaseNoLater(picklerPhase) {
1395+
atPhaseBeforeTransforms {
13961396
op(reader)(using ctx
13971397
.withOwner(owner)
13981398
.withModeBits(mode)

compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
608608
}
609609
atReadPos(startCoord(denot).toIndex,
610610
() => withMode(Mode.Scala2Unpickling) {
611-
atPhaseNoLater(picklerPhase) {
611+
atPhaseBeforeTransforms {
612612
parseToCompletion(denot)
613613
}
614614
})

0 commit comments

Comments
 (0)