diff options
author | Den Shabalin <den.shabalin@gmail.com> | 2013-12-08 20:18:56 +0100 |
---|---|---|
committer | Den Shabalin <den.shabalin@gmail.com> | 2013-12-16 14:07:40 +0100 |
commit | b97d44b2d813c1bf482b23efb353e4550818700c (patch) | |
tree | de432783867f16d86a016296156a793fa46b110c /test/files | |
parent | 75cc6cf256df9e152eaec771121ce0db9f7039f8 (diff) | |
download | scala-b97d44b2d813c1bf482b23efb353e4550818700c.tar.gz scala-b97d44b2d813c1bf482b23efb353e4550818700c.tar.bz2 scala-b97d44b2d813c1bf482b23efb353e4550818700c.zip |
SI-8047 change fresh name encoding to avoid owner corruption
Previously a following encoding was used to represent fresh
names that should be created at runtime of the quasiquote:
build.withFreshTermName(prefix1) { name$1 =>
...
build.withFreshTermName(prefixN) { name$N =>
tree
}
...
}
It turned out that this encoding causes symbol corruption when
tree defines symbols of its own. After being spliced into anonymous
functions, the owner chain of those symbols will become corrupted.
Now a simpler and probably better performing alternative is
used instead:
{
val name$1 = universe.build.freshTermName(prefix1)
...
val name$N = universe.build.freshTermName(prefixN)
tree
}
Here owner stays the same and doesn’t need any adjustment.
Diffstat (limited to 'test/files')
-rw-r--r-- | test/files/run/t8047.check | 7 | ||||
-rw-r--r-- | test/files/run/t8047.scala | 31 |
2 files changed, 38 insertions, 0 deletions
diff --git a/test/files/run/t8047.check b/test/files/run/t8047.check new file mode 100644 index 0000000000..a6b83a4a16 --- /dev/null +++ b/test/files/run/t8047.check @@ -0,0 +1,7 @@ +doWhile$1(){ + 1; + if (true) + doWhile$1() + else + () +} diff --git a/test/files/run/t8047.scala b/test/files/run/t8047.scala new file mode 100644 index 0000000000..f5660541e8 --- /dev/null +++ b/test/files/run/t8047.scala @@ -0,0 +1,31 @@ +object Test extends App { + import scala.reflect.runtime.universe._ + // + // x's owner is outer Test scope. Previosly the quasiquote expansion + // looked like: + // + // object Test { + // build.withFreshTermName("doWhile")(n => + // LabelDef(n, List(), + // Block( + // List({ val x = 1; x }), + // If(Literal(Constant(true)), Apply(Ident(n), List()), Literal(Constant(()))))) + // } + // + // Here the proper owner is anonymous function, not the Test. Hence + // symbol corruption. In new encoding this is represented as: + // + // object Test { + // { + // val n = build.freshTermName("doWhile") + // LabelDef(n, List(), + // Block( + // List({ val x = 1; x }), + // If(Literal(Constant(true)), Apply(Ident(n), List()), Literal(Constant(())))) + // } + // } + // + // Owner stays the same and life is good again. + // + println(q"do ${ val x = 1; x } while(true)") +} |