Skip to content

Commit 412906e

Browse files
committed
Move ByNameClosure earlier in the pipleline
- Make it use changeOwnerAfter - Factor out TransformByNameApply as a common base trait between it and ElimByName
1 parent dee06a5 commit 412906e

File tree

5 files changed

+73
-51
lines changed

5 files changed

+73
-51
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class Compiler {
5555
new ExtensionMethods, // Expand methods of value classes with extension methods
5656
new ExpandSAMs, // Expand single abstract method closures to anonymous classes
5757
new TailRec, // Rewrite tail recursion to loops
58+
new ByNameClosures), List( // Expand by-name arguments
5859
new LiftTry, // Put try expressions that might execute on non-empty stacks into their own methods
5960
new ClassOf), // Expand `Predef.classOf` calls.
6061
List(new TryCatchPatterns, // Compile cases in try/catch
@@ -69,7 +70,7 @@ class Compiler {
6970
new SeqLiterals, // Express vararg arguments as arrays
7071
new InterceptedMethods, // Special handling of `==`, `|=`, `getClass` methods
7172
new Getters, // Replace non-private vals and vars with getter defs (fields are added later)
72-
new ElimByName, // Expand by-name parameters and arguments
73+
new ElimByName, // Expand by-name parameters
7374
new AugmentScala2Traits, // Expand traits defined in Scala 2.11 to simulate old-style rewritings
7475
new ResolveSuper, // Implement super accessors and add forwarders to trait methods
7576
new PrimitiveForwarders, // Add forwarders to trait methods that have a mismatch between generic and primitives

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

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import Contexts._
99
import Types._
1010
import Flags._
1111
import Decorators._
12+
import DenotTransformers.IdentityDenotTransformer
1213
import core.StdNames.nme
13-
import ast.Trees._
1414

1515
/** This phase translates arguments to call-by-name parameters, using the rules
1616
*
@@ -24,55 +24,15 @@ import ast.Trees._
2424
*
2525
* is a synthetic method defined in Definitions. Erasure will later strip these DummyApply wrappers.
2626
*/
27-
class ByNameClosures extends MiniPhaseTransform { thisTransformer =>
27+
class ByNameClosures extends TransformByNameApply with IdentityDenotTransformer { thisTransformer =>
2828
import ast.tpd._
2929

3030
override def phaseName: String = "bynameClosures"
3131

32-
/** The info of the tree's symbol at phase Nullarify (i.e. before transformation) */
33-
private def originalDenotation(tree: Tree)(implicit ctx: Context) =
34-
tree.symbol.denot(ctx.withPhase(thisTransformer))
35-
36-
/** If denotation had an ExprType before, it now gets a function type */
37-
protected def exprBecomesFunction(symd: SymDenotation)(implicit ctx: Context) =
38-
(symd is Param) || (symd is (ParamAccessor, butNot = Method))
39-
40-
protected def isByNameRef(tree: Tree)(implicit ctx: Context) = {
41-
val origDenot = originalDenotation(tree)
42-
origDenot.info.isInstanceOf[ExprType] && exprBecomesFunction(origDenot)
43-
}
44-
45-
override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree =
46-
ctx.traceIndented(s"transforming ${tree.show} at phase ${ctx.phase}", show = true) {
47-
48-
def transformArg(arg: Tree, formal: Type): Tree = formal.dealias match {
49-
case formalExpr: ExprType =>
50-
var argType = arg.tpe.widenIfUnstable
51-
if (defn.isBottomType(argType)) argType = formal.widenExpr
52-
def wrap(arg: Tree) = ref(defn.dummyApply).appliedToType(argType).appliedTo(arg)
53-
arg match {
54-
case Apply(Select(qual, nme.apply), Nil)
55-
if qual.tpe.derivesFrom(defn.FunctionClass(0)) && isPureExpr(qual) =>
56-
wrap(qual)
57-
case _ =>
58-
if (isByNameRef(arg) || arg.symbol == defn.dummyApply) arg
59-
else {
60-
val inSuper = if (ctx.mode.is(Mode.InSuperCall)) InSuperCall else EmptyFlags
61-
val meth = ctx.newSymbol(
62-
ctx.owner, nme.ANON_FUN, Synthetic | Method | inSuper, MethodType(Nil, Nil, argType))
63-
wrap(Closure(meth, _ =>
64-
atGroupEnd { implicit ctx: Context =>
65-
arg.changeOwner(ctx.owner, meth)
66-
}
67-
))
68-
}
69-
}
70-
case _ =>
71-
arg
72-
}
73-
74-
val mt @ MethodType(_) = tree.fun.tpe.widen
75-
val args1 = tree.args.zipWithConserve(mt.paramInfos)(transformArg)
76-
cpy.Apply(tree)(tree.fun, args1)
32+
override def mkClosure(arg: Tree, argType: Type)(implicit ctx: Context): Tree = {
33+
val inSuper = if (ctx.mode.is(Mode.InSuperCall)) InSuperCall else EmptyFlags
34+
val meth = ctx.newSymbol(
35+
ctx.owner, nme.ANON_FUN, Synthetic | Method | inSuper, MethodType(Nil, Nil, argType))
36+
Closure(meth, _ => arg.changeOwnerAfter(ctx.owner, meth, thisTransformer))
7737
}
7838
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package transform
33

44
import TreeTransforms._
55
import core._
6-
import DenotTransformers._
6+
import DenotTransformers.InfoTransformer
77
import Symbols._
88
import SymDenotations._
99
import Contexts._
@@ -38,7 +38,7 @@ import ast.Trees._
3838
* Option 2: Merge ElimByName with erasure, or have it run immediately before. This has not been
3939
* tried yet.
4040
*/
41-
class ElimByName extends ByNameClosures with InfoTransformer { thisTransformer =>
41+
class ElimByName extends TransformByNameApply with InfoTransformer { thisTransformer =>
4242
import ast.tpd._
4343

4444
override def phaseName: String = "elimByName"
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import TreeTransforms._
5+
import core._
6+
import Symbols._
7+
import SymDenotations._
8+
import Contexts._
9+
import Types._
10+
import Flags._
11+
import Decorators._
12+
import DenotTransformers._
13+
import core.StdNames.nme
14+
import ast.Trees._
15+
16+
/** Abstract base class of ByNameClosures and ELimByName, factoring out the
17+
* common functionality to transform arguments of by-name parameters.
18+
*/
19+
abstract class TransformByNameApply extends MiniPhaseTransform { thisTransformer: DenotTransformer =>
20+
import ast.tpd._
21+
22+
/** The info of the tree's symbol at phase Nullarify (i.e. before transformation) */
23+
private def originalDenotation(tree: Tree)(implicit ctx: Context) =
24+
tree.symbol.denot(ctx.withPhase(thisTransformer))
25+
26+
/** If denotation had an ExprType before, it now gets a function type */
27+
protected def exprBecomesFunction(symd: SymDenotation)(implicit ctx: Context) =
28+
(symd is Param) || (symd is (ParamAccessor, butNot = Method))
29+
30+
protected def isByNameRef(tree: Tree)(implicit ctx: Context) = {
31+
val origDenot = originalDenotation(tree)
32+
origDenot.info.isInstanceOf[ExprType] && exprBecomesFunction(origDenot)
33+
}
34+
35+
def mkClosure(arg: Tree, argType: Type)(implicit ctx: Context): Tree = unsupported("mkClosure")
36+
37+
override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree =
38+
ctx.traceIndented(s"transforming ${tree.show} at phase ${ctx.phase}", show = true) {
39+
40+
def transformArg(arg: Tree, formal: Type): Tree = formal.dealias match {
41+
case formalExpr: ExprType =>
42+
var argType = arg.tpe.widenIfUnstable
43+
if (defn.isBottomType(argType)) argType = formal.widenExpr
44+
def wrap(arg: Tree) = ref(defn.dummyApply).appliedToType(argType).appliedTo(arg)
45+
arg match {
46+
case Apply(Select(qual, nme.apply), Nil)
47+
if qual.tpe.derivesFrom(defn.FunctionClass(0)) && isPureExpr(qual) =>
48+
wrap(qual)
49+
case _ =>
50+
if (isByNameRef(arg) || arg.symbol == defn.dummyApply) arg
51+
else wrap(mkClosure(arg, argType))
52+
}
53+
case _ =>
54+
arg
55+
}
56+
57+
val mt @ MethodType(_) = tree.fun.tpe.widen
58+
val args1 = tree.args.zipWithConserve(mt.paramInfos)(transformArg)
59+
cpy.Apply(tree)(tree.fun, args1)
60+
}
61+
}

tests/neg/tailcall/t1672b.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ object Test1772B {
4646
else 1 + (try {
4747
throw new RuntimeException
4848
} catch {
49-
case _: Throwable => bar(i - 1) // old-error
49+
case _: Throwable => bar(i - 1) // error
5050
})
5151
}
5252
}

0 commit comments

Comments
 (0)