Skip to content

Commit f492d0a

Browse files
committed
SI-5788 Tailcalls LabelDefs correctly duplicated
... in specialization. This is a quick hack to get SI-5788 fixed in 2.10.x. The full patch, which fixes the tailcalls LabelDefs will be merged into trunk, as it's too late for big changes. For reference, the complete fix is: e86afe6
1 parent ba402c4 commit f492d0a

File tree

2 files changed

+23
-12
lines changed

2 files changed

+23
-12
lines changed

src/compiler/scala/tools/nsc/typechecker/Duplicators.scala

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ abstract class Duplicators extends Analyzer {
4141
}
4242

4343
protected def newBodyDuplicator(context: Context) = new BodyDuplicator(context)
44-
44+
4545
def retypedMethod(context: Context, tree: Tree, oldThis: Symbol, newThis: Symbol): Tree =
4646
(newBodyDuplicator(context)).retypedMethod(tree.asInstanceOf[DefDef], oldThis, newThis)
4747

@@ -160,7 +160,7 @@ abstract class Duplicators extends Analyzer {
160160
newsym.setInfo(fixType(ldef.symbol.info))
161161
ldef.symbol = newsym
162162
debuglog("newsym: " + newsym + " info: " + newsym.info)
163-
163+
164164
case vdef @ ValDef(mods, name, _, rhs) if mods.hasFlag(Flags.LAZY) =>
165165
debuglog("ValDef " + name + " sym.info: " + vdef.symbol.info)
166166
invalidSyms(vdef.symbol) = vdef
@@ -170,7 +170,7 @@ abstract class Duplicators extends Analyzer {
170170
vdef.symbol = newsym
171171
debuglog("newsym: " + newsym + " info: " + newsym.info + ", owner: " + newsym.owner + ", " + newsym.owner.isClass)
172172
if (newsym.owner.isClass) newsym.owner.info.decls enter newsym
173-
173+
174174
case DefDef(_, name, tparams, vparamss, _, rhs) =>
175175
// invalidate parameters
176176
invalidateAll(tparams ::: vparamss.flatten)
@@ -215,7 +215,7 @@ abstract class Duplicators extends Analyzer {
215215
* Unless overridden, just returns the tree.
216216
*/
217217
def castType(tree: Tree, pt: Type): Tree = tree
218-
218+
219219
/** Special typer method for re-type checking trees. It expects a typed tree.
220220
* Returns a typed tree that has fresh symbols for all definitions in the original tree.
221221
*
@@ -278,12 +278,19 @@ abstract class Duplicators extends Analyzer {
278278
invalidate(rhs)
279279
ldef.tpe = null
280280

281-
// since typer does not create the symbols for a LabelDef's params,
282-
// we do that manually here -- we should really refactor LabelDef to be a subclass of DefDef
283-
def newParam(p: Tree): Ident = {
284-
val newsym = p.symbol.cloneSymbol //(context.owner) // TODO owner?
285-
Ident(newsym.setInfo(fixType(p.symbol.info)))
286-
}
281+
// is this LabelDef generated by tailcalls?
282+
val isTailLabel = (ldef.params.length >= 1) && (ldef.params.head.name == nme.THIS)
283+
284+
// the typer does not create the symbols for a LabelDef's params, so unless they were created before we need
285+
// to do it manually here -- but for the tailcalls-generated labels, ValDefs are created before the LabelDef,
286+
// so we just need to plug in the name
287+
def newParam(p: Tree): Ident =
288+
if (isTailLabel)
289+
Ident(p.symbol.name) // let the typer pick up the right symbol
290+
else {
291+
val newsym = p.symbol.cloneSymbol //(context.owner) // TODO owner?
292+
Ident(newsym.setInfo(fixType(p.symbol.info)))
293+
}
287294
val params1 = params map newParam
288295
val rhs1 = (new TreeSubstituter(params map (_.symbol), params1) transform rhs) // TODO: duplicate?
289296
rhs1.tpe = null
@@ -365,7 +372,7 @@ abstract class Duplicators extends Analyzer {
365372
case EmptyTree =>
366373
// no need to do anything, in particular, don't set the type to null, EmptyTree.tpe_= asserts
367374
tree
368-
375+
369376
case _ =>
370377
debuglog("Duplicators default case: " + tree.summaryString)
371378
debuglog(" ---> " + tree)
@@ -376,7 +383,7 @@ abstract class Duplicators extends Analyzer {
376383
super.typed(ntree, mode, pt)
377384
}
378385
}
379-
386+
380387
}
381388
}
382389

test/files/pos/SI-5788.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
trait Test {
2+
trait B[T]
3+
private final def grow[T](): B[T] = grow[T]()
4+
}

0 commit comments

Comments
 (0)