Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Commit 2aa685b

Browse files
author
Aleksandar Prokopec
committed
Fixes SI-4717.
A lazy val declared inside an anonymous class inside a specialized context no longer crashes Duplicators. Previously, a duplicated lazy val was assigned to the wrong owner in Duplicators: def x[B >: A]: Unit = new Bounds[B] { lazy val it = ??? // def or val okay } Above, the `it` in `$anon` in `x$mcZ$sp` had its owner set to `x$mcZ$sp` instead of `$anon`. This crashed the typer when it had to retype its lazy accessor, because there was no `lazy var it` in `$anon$`. Furthermore, the duplicated symbol wasn't being added to the list of declarations of `$anon`. Changes: 1) `invalidate` in Duplicators takes an additional parameter which is the new owner of the new symbol that has to be duplicated. If this parameter is set to `NoSymbol`, then the new owner is `context.owner`, as before. 2) the newly created lazy val symbol is being added to the list of declarations of its new owner. Removes debugging output from the previous commit. Review by dragos. @mention dragos
1 parent c7699eb commit 2aa685b

File tree

4 files changed

+22
-38
lines changed

4 files changed

+22
-38
lines changed

src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1550,7 +1550,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
15501550
val meth = addBody(tree, source)
15511551

15521552
val d = new Duplicator
1553-
log("-->d DUPLICATING: " + meth)
1553+
debuglog("-->d DUPLICATING: " + meth)
15541554
d.retyped(
15551555
localTyper.context1.asInstanceOf[d.Context],
15561556
meth,

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

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ abstract class Duplicators extends Analyzer {
143143
else
144144
sym
145145

146-
private def invalidate(tree: Tree) {
147-
log("attempting to invalidate " + tree.symbol + ", owner - " + (if (tree.symbol ne null) tree.symbol.owner else "<NULL>"))
146+
private def invalidate(tree: Tree, owner: Symbol = NoSymbol) {
147+
debuglog("attempting to invalidate " + tree.symbol)
148148
if (tree.isDef && tree.symbol != NoSymbol) {
149149
debuglog("invalid " + tree.symbol)
150150
invalidSyms(tree.symbol) = tree
@@ -158,18 +158,20 @@ abstract class Duplicators extends Analyzer {
158158
newsym.setInfo(fixType(ldef.symbol.info))
159159
ldef.symbol = newsym
160160
debuglog("newsym: " + newsym + " info: " + newsym.info)
161-
161+
162162
case vdef @ ValDef(mods, name, _, rhs) if mods.hasFlag(Flags.LAZY) =>
163-
log("ValDef " + name + " sym.info: " + vdef.symbol.info + ", owner: " + vdef.symbol.owner + " vs. context owner: " + context.owner)
163+
debuglog("ValDef " + name + " sym.info: " + vdef.symbol.info)
164164
invalidSyms(vdef.symbol) = vdef
165-
val newsym = vdef.symbol.cloneSymbol(context.owner)
165+
val newowner = if (owner != NoSymbol) owner else context.owner
166+
val newsym = vdef.symbol.cloneSymbol(newowner)
166167
newsym.setInfo(fixType(vdef.symbol.info))
167168
vdef.symbol = newsym
168-
log("newsym: " + newsym + " info: " + newsym.info + ", " + newsym.owner + ", whereas symbol.owner is: " + vdef.symbol.owner)
169-
169+
newsym.owner.info.decls enter newsym
170+
debuglog("newsym: " + newsym + " info: " + newsym.info)
171+
170172
case DefDef(_, name, tparams, vparamss, _, rhs) =>
171173
// invalidate parameters
172-
invalidate(tparams ::: vparamss.flatten)
174+
invalidateAll(tparams ::: vparamss.flatten)
173175
tree.symbol = NoSymbol
174176

175177
case _ =>
@@ -178,14 +180,14 @@ abstract class Duplicators extends Analyzer {
178180
}
179181
}
180182

181-
private def invalidate(stats: List[Tree]) {
182-
stats foreach invalidate
183+
private def invalidateAll(stats: List[Tree], owner: Symbol = NoSymbol) {
184+
stats.foreach(invalidate(_, owner))
183185
}
184186

185187
def retypedMethod(ddef: DefDef, oldThis: Symbol, newThis: Symbol): Tree = {
186188
oldClassOwner = oldThis
187189
newClassOwner = newThis
188-
invalidate(ddef.tparams)
190+
invalidateAll(ddef.tparams)
189191
mforeach(ddef.vparamss) { vdef =>
190192
invalidate(vdef)
191193
vdef.tpe = null
@@ -239,15 +241,15 @@ abstract class Duplicators extends Analyzer {
239241

240242
case Block(stats, res) =>
241243
debuglog("invalidating block")
242-
invalidate(stats)
244+
invalidateAll(stats)
243245
invalidate(res)
244246
tree.tpe = null
245247
super.typed(tree, mode, pt)
246248

247249
case ClassDef(_, _, _, tmpl @ Template(parents, _, stats)) =>
248-
log("invalidating classdef " + tree.tpe)
250+
// log("invalidating classdef " + tree)
249251
tmpl.symbol = tree.symbol.newLocalDummy(tree.pos)
250-
invalidate(stats)
252+
invalidateAll(stats, tree.symbol)
251253
tree.tpe = null
252254
super.typed(tree, mode, pt)
253255

@@ -257,7 +259,6 @@ abstract class Duplicators extends Analyzer {
257259
super.typed(ddef, mode, pt)
258260

259261
case vdef @ ValDef(mods, name, tpt, rhs) =>
260-
log("vdef: " + vdef)
261262
// log("vdef fixing tpe: " + tree.tpe + " with sym: " + tree.tpe.typeSymbol + " and " + invalidSyms)
262263
//if (mods.hasFlag(Flags.LAZY)) vdef.symbol.resetFlag(Flags.MUTABLE) // Martin to Iulian: lazy vars can now appear because they are no longer boxed; Please check that deleting this statement is OK.
263264
vdef.tpt.tpe = fixType(vdef.tpt.tpe)
@@ -359,15 +360,11 @@ abstract class Duplicators extends Analyzer {
359360
tree
360361

361362
case _ =>
362-
log("Duplicators default case: " + tree.summaryString)
363+
debuglog("Duplicators default case: " + tree.summaryString)
363364
if (tree.hasSymbol && tree.symbol != NoSymbol && (tree.symbol.owner == definitions.AnyClass)) {
364365
tree.symbol = NoSymbol // maybe we can find a more specific member in a subclass of Any (see AnyVal members, like ==)
365366
}
366367
tree.tpe = null
367-
tree match {
368-
case Select(q, n) => log("Select: " + q + ", " + n + " = " + q.tpe.member(n) + ", members: " + q.tpe.members)
369-
case _ => log(tree.getClass)
370-
}
371368
super.typed(tree, mode, pt)
372369
}
373370
}

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

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3657,10 +3657,6 @@ trait Typers extends Modes with Adaptations with Taggings {
36573657

36583658
def typed1(tree: Tree, mode: Int, pt: Type): Tree = {
36593659
def isPatternMode = inPatternMode(mode)
3660-
tree match {
3661-
case This(_) => log("typed1: " + tree + ", " + tree.tpe)
3662-
case _ =>
3663-
}
36643660

36653661
//Console.println("typed1("+tree.getClass()+","+Integer.toHexString(mode)+","+pt+")")
36663662
//@M! get the type of the qualifier in a Select tree, otherwise: NoType
@@ -4239,7 +4235,6 @@ trait Typers extends Modes with Adaptations with Taggings {
42394235
def typedThis(qual: Name) = tree.symbol orElse qualifyingClass(tree, qual, packageOK = false) match {
42404236
case NoSymbol => tree
42414237
case clazz =>
4242-
log("typedThis: " + qual + ", " + clazz.thisType.underlying)
42434238
tree setSymbol clazz setType clazz.thisType.underlying
42444239
if (isStableContext(tree, mode, pt)) tree setType clazz.thisType else tree
42454240
}
@@ -4252,7 +4247,6 @@ trait Typers extends Modes with Adaptations with Taggings {
42524247
* @return ...
42534248
*/
42544249
def typedSelect(qual: Tree, name: Name): Tree = {
4255-
log("typedSelect: " + qual + ", name: " + name + ", member: " + (qual.tpe.members))
42564250
def asDynamicCall = dyna.mkInvoke(context.tree, tree, qual, name) map (typed1(_, mode, pt))
42574251

42584252
val sym = tree.symbol orElse member(qual, name) orElse {
@@ -4876,12 +4870,9 @@ trait Typers extends Modes with Adaptations with Taggings {
48764870

48774871
case Select(qual, name) =>
48784872
incCounter(typedSelectCount)
4879-
val tpq = typedQualifier(qual, mode)
4880-
if (qual.tpe ne null) log("Select: " + qual + ", " + name + " = " + qual.tpe.member(name) + ", members: " + qual.tpe.members)
4881-
var qual1 = checkDead(tpq)
4873+
var qual1 = checkDead(typedQualifier(qual, mode))
48824874
if (name.isTypeName) qual1 = checkStable(qual1)
4883-
log("members: " + qual.tpe.members)
4884-
4875+
48854876
val tree1 = // temporarily use `filter` and an alternative for `withFilter`
48864877
if (name == nme.withFilter)
48874878
silent(_ => typedSelect(qual1, name)) match {

test/files/pos/t4717.scala

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55

66

7-
/*
7+
88
trait Bug1[@specialized(Boolean) A] extends TraversableOnce[A] {
99

1010
def ++[B >: A](that: TraversableOnce[B]): Iterator[B] = new Iterator[B] {
@@ -14,25 +14,21 @@ trait Bug1[@specialized(Boolean) A] extends TraversableOnce[A] {
1414
}
1515

1616
}
17-
*/
1817

1918

20-
/*
19+
2120
trait WorksFine[@specialized(Boolean) A] {
2221
class SubBounds[B >: A] extends Bounds[B] {
2322
lazy val it = ???
24-
it
2523
}
2624
def x[B >: A]: Unit = new SubBounds[B]
2725
}
28-
*/
2926

3027

3128
trait Bounds[@specialized(Boolean) A] {
3229
// okay without `>: A`
3330
def x[B >: A]: Unit = new Bounds[B] {
3431
lazy val it = ??? // def or val okay
35-
it
3632
}
3733
}
3834

0 commit comments

Comments
 (0)