Skip to content

Commit 79188be

Browse files
committed
Implement step 2 of SIP-15: Rerouting value classes calls
1 parent 826864b commit 79188be

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

src/dotty/tools/dotc/transform/ElimRepeated.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
6161
override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = {
6262
val args1 = tree.args.map {
6363
case arg: Typed if isWildcardStarArg(arg) =>
64-
if (tree.fun.symbol.is(JavaDefined) && arg.expr.tpe.derivesFrom(defn.SeqClass))
64+
// `atGroupEnd` is needed because the miniphase ExtensionMethods is run after this miniphase
65+
// and can create new function symbols.
66+
val javaFun = atGroupEnd { implicit ctx => tree.fun.symbol is JavaDefined }
67+
if (javaFun && arg.expr.tpe.derivesFrom(defn.SeqClass))
6568
seqToArray(arg.expr)
6669
else arg.expr
6770
case arg => arg

src/dotty/tools/dotc/transform/ExtensionMethods.scala

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import util.Positions._
1919
import Decorators._
2020

2121
/**
22-
* Perform Step 1 in the inline classes SIP: Creates extension methods for all
22+
* Perform Step 1 and 2 in the value classes SIP: Creates extension methods for all
2323
* methods in a value class, except parameter or super accessors, or constructors.
2424
*/
2525
class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with FullParameterization { thisTransformer =>
@@ -181,4 +181,39 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
181181
cpy.DefDef(tree)(rhs = atGroupEnd(forwarder(extensionMeth, tree)(_)))
182182
} else tree
183183
}
184+
185+
/** Implement Step 2 of SIP-15: rerouting calls.
186+
* Note that this is different from Scala 2 which did the rerouting much later in
187+
* the PostErasure phase.
188+
* TODO: avoid code duplication with fullyParameterizedDef#rewireTree
189+
*/
190+
private def rewire(select: Select, targs: List[Tree])(implicit ctx: Context): Tree = {
191+
val Select(qual, _) = select
192+
val origMeth = select.symbol
193+
if (isMethodWithExtension(origMeth)) {
194+
val extensionMeth = extensionMethod(origMeth)
195+
val origClass = origMeth.enclosingClass.asClass
196+
val base = qual.tpe.baseTypeWithArgs(origClass)
197+
assert(base.exists)
198+
ref(extensionMeth)
199+
.appliedToTypeTrees(targs ++ base.argInfos.map(TypeTree(_)))
200+
.appliedTo(qual)
201+
} else EmptyTree
202+
}
203+
204+
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree =
205+
tree match {
206+
case TypeApply(sel @ Select(_,_), args) =>
207+
rewire(sel, args) orElse tree
208+
case _ =>
209+
tree
210+
}
211+
212+
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree =
213+
tree.tpe.widen match {
214+
case tp: PolyType =>
215+
tree // The rewiring will be handled by transformTypeApply
216+
case tp =>
217+
rewire(tree, Nil) orElse tree
218+
}
184219
}

0 commit comments

Comments
 (0)