Skip to content

Commit 8993b6b

Browse files
committed
Merge pull request #43 from retronym/ticket/icode-crasher
Fix crasher in icode due to symbol mismatches in lifted methods
2 parents 9500b04 + df2ebee commit 8993b6b

File tree

2 files changed

+94
-37
lines changed

2 files changed

+94
-37
lines changed

src/main/scala/scala/async/internal/Lifter.scala

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -105,45 +105,52 @@ trait Lifter {
105105
}
106106

107107
val lifted = liftableSyms.map(symToTree).toList.map {
108-
case vd@ValDef(_, _, tpt, rhs) =>
109-
import reflect.internal.Flags._
110-
val sym = vd.symbol
111-
sym.setFlag(MUTABLE | STABLE | PRIVATE | LOCAL)
112-
sym.name = name.fresh(sym.name.toTermName)
113-
sym.modifyInfo(_.deconst)
114-
ValDef(vd.symbol, gen.mkZero(vd.symbol.info)).setPos(vd.pos)
115-
case dd@DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
116-
import reflect.internal.Flags._
117-
val sym = dd.symbol
118-
sym.name = this.name.fresh(sym.name.toTermName)
119-
sym.setFlag(PRIVATE | LOCAL)
120-
DefDef(dd.symbol, rhs).setPos(dd.pos)
121-
case cd@ClassDef(_, _, _, impl) =>
122-
import reflect.internal.Flags._
123-
val sym = cd.symbol
124-
sym.name = newTypeName(name.fresh(sym.name.toString).toString)
125-
companionship.companionOf(cd.symbol) match {
126-
case NoSymbol =>
127-
case moduleSymbol =>
128-
moduleSymbol.name = sym.name.toTermName
129-
moduleSymbol.moduleClass.name = moduleSymbol.name.toTypeName
130-
}
131-
ClassDef(cd.symbol, impl).setPos(cd.pos)
132-
case md@ModuleDef(_, _, impl) =>
133-
import reflect.internal.Flags._
134-
val sym = md.symbol
135-
companionship.companionOf(md.symbol) match {
136-
case NoSymbol =>
108+
t =>
109+
val treeLifted = t match {
110+
case vd@ValDef(_, _, tpt, rhs) =>
111+
import reflect.internal.Flags._
112+
val sym = vd.symbol
113+
sym.setFlag(MUTABLE | STABLE | PRIVATE | LOCAL)
137114
sym.name = name.fresh(sym.name.toTermName)
138-
sym.moduleClass.name = sym.name.toTypeName
139-
case classSymbol => // will be renamed by `case ClassDef` above.
115+
sym.modifyInfo(_.deconst)
116+
val zeroRhs = atPos(t.pos)(gen.mkZero(vd.symbol.info))
117+
treeCopy.ValDef(vd, Modifiers(sym.flags), sym.name, TypeTree(sym.tpe).setPos(t.pos), zeroRhs)
118+
case dd@DefDef(_, _, tparams, vparamss, tpt, rhs) =>
119+
import reflect.internal.Flags._
120+
val sym = dd.symbol
121+
sym.name = this.name.fresh(sym.name.toTermName)
122+
sym.setFlag(PRIVATE | LOCAL)
123+
// Was `DefDef(sym, rhs)`, but this ran afoul of `ToughTypeSpec.nestedMethodWithInconsistencyTreeAndInfoParamSymbols`
124+
// due to the handling of type parameter skolems in `thisMethodType` in `Namers`
125+
treeCopy.DefDef(dd, Modifiers(sym.flags), sym.name, tparams, vparamss, tpt, rhs)
126+
case cd@ClassDef(_, _, tparams, impl) =>
127+
import reflect.internal.Flags._
128+
val sym = cd.symbol
129+
sym.name = newTypeName(name.fresh(sym.name.toString).toString)
130+
companionship.companionOf(cd.symbol) match {
131+
case NoSymbol =>
132+
case moduleSymbol =>
133+
moduleSymbol.name = sym.name.toTermName
134+
moduleSymbol.moduleClass.name = moduleSymbol.name.toTypeName
135+
}
136+
treeCopy.ClassDef(cd, Modifiers(sym.flags), sym.name, tparams, impl)
137+
case md@ModuleDef(_, _, impl) =>
138+
import reflect.internal.Flags._
139+
val sym = md.symbol
140+
companionship.companionOf(md.symbol) match {
141+
case NoSymbol =>
142+
sym.name = name.fresh(sym.name.toTermName)
143+
sym.moduleClass.name = sym.name.toTypeName
144+
case classSymbol => // will be renamed by `case ClassDef` above.
145+
}
146+
treeCopy.ModuleDef(md, Modifiers(sym.flags), sym.name, impl)
147+
case td@TypeDef(_, _, tparams, rhs) =>
148+
import reflect.internal.Flags._
149+
val sym = td.symbol
150+
sym.name = newTypeName(name.fresh(sym.name.toString).toString)
151+
treeCopy.TypeDef(td, Modifiers(sym.flags), sym.name, tparams, rhs)
140152
}
141-
ModuleDef(md.symbol, impl).setPos(md.pos)
142-
case td@TypeDef(_, _, _, rhs) =>
143-
import reflect.internal.Flags._
144-
val sym = td.symbol
145-
sym.name = newTypeName(name.fresh(sym.name.toString).toString)
146-
TypeDef(td.symbol, rhs).setPos(td.pos)
153+
atPos(t.pos)(treeLifted)
147154
}
148155
lifted
149156
}

src/test/scala/scala/async/run/toughtype/ToughType.scala

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,59 @@ class ToughTypeSpec {
135135
}
136136
foo
137137
}
138+
139+
// This test was failing when lifting `def r` with:
140+
// symbol value m#10864 does not exist in r$1
141+
//
142+
// We generated:
143+
//
144+
// private[this] def r$1#5727[A#5728 >: Nothing#157 <: Any#156](m#5731: Foo#2349[A#5728]): Unit#208 = Bippy#2352.this.bar#5532({
145+
// m#5730;
146+
// ()
147+
// });
148+
//
149+
// Notice the incorrect reference to `m`.
150+
//
151+
// We compensated in `Lifter` by copying `ValDef` parameter symbols directly across.
152+
//
153+
// Turns out the behaviour stems from `thisMethodType` in `Namers`, which treats type parameter skolem symbols.
154+
@Test def nestedMethodWithInconsistencyTreeAndInfoParamSymbols() {
155+
import language.{reflectiveCalls, postfixOps}
156+
import scala.concurrent.{Future, ExecutionContext, future, Await}
157+
import scala.concurrent.duration._
158+
import scala.async.Async.{async, await}
159+
import scala.async.internal.AsyncId
160+
161+
class Foo[A]
162+
163+
object Bippy {
164+
165+
import ExecutionContext.Implicits.global
166+
167+
def bar(f: => Unit): Unit = f
168+
169+
def quux: Future[String] = ???
170+
171+
def foo = async {
172+
def r[A](m: Foo[A])(n: A) = {
173+
bar {
174+
locally(m)
175+
locally(n)
176+
identity[A] _
177+
}
178+
}
179+
180+
await(quux)
181+
182+
r(new Foo[String])("")
183+
}
184+
}
185+
Bippy
186+
}
138187
}
139188

140189
trait A
190+
141191
trait B
142192

143193
trait L[A2, B2 <: A2] {

0 commit comments

Comments
 (0)