summaryrefslogtreecommitdiff
path: root/test/files/run/t8245.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-02-08 09:45:07 +0100
committerJason Zaugg <jzaugg@gmail.com>2014-02-08 10:58:57 +0100
commit46d84194a46033f945f9cfc7c4f61f52b0c3ae9e (patch)
tree07cc16bbd38fa42e6575d615fb1abee5184c0829 /test/files/run/t8245.scala
parent3306967c561e3ea34306419d5351b4e20673cc8b (diff)
downloadscala-46d84194a46033f945f9cfc7c4f61f52b0c3ae9e.tar.gz
scala-46d84194a46033f945f9cfc7c4f61f52b0c3ae9e.tar.bz2
scala-46d84194a46033f945f9cfc7c4f61f52b0c3ae9e.zip
SI-8245 Fix regression in interplay between lazy val, return
In 4c86dbbc492 / SI-6358, synthesis of lazy val accessors trees was moved into the typer phase (in MethodSynthesis). Before that point, the symobl for the accessor *was* created early, but the tree was not. This led to crashes in intervening phases (extensionmethods) as `changeOwner` calls didn't catch the smuggled symbol. Moving the accessor generation forward, however, brought a problem: we now introduce a DefDef around the RHS of the lazy val, but we're not actually guaranteed that the body has already been typechecked. If it happened to be typechecked for the purposes of return type inference, we'll pick up the typechecked tree from `transformed`: // LazyValGetter#derivedTree val rhs1 = transformed.getOrElse(rhs0, rhs0) But if the method had an explicit return type (which must *always* be the case if it contains a `return`!), `rhs0` will be untyped. This leads to, e.g.: def foo(o: Option[Int]): Int = { lazy val i = o.getOrElse(return -1) i + 1 } def foo(o: Option[Int]): Int = { lazy <artifact> var i$lzy: Int = _; <stable> <accessor> lazy def i: Int = { i$lzy = o.getOrElse(return -1); i$lzy }; i.+(1) }; When this is typechecked, the `return` binds to the closest enclosing `DefDef`, `lazy def i`. This commit changes `Context#enclMethod` to treat `DefDef`s as transparent. `enclMethod` is only used in one other spot that enforces the implementation restriction that "module extending its companion class cannot use default constructor arguments".
Diffstat (limited to 'test/files/run/t8245.scala')
-rw-r--r--test/files/run/t8245.scala14
1 files changed, 14 insertions, 0 deletions
diff --git a/test/files/run/t8245.scala b/test/files/run/t8245.scala
new file mode 100644
index 0000000000..d44defbb9e
--- /dev/null
+++ b/test/files/run/t8245.scala
@@ -0,0 +1,14 @@
+object Test {
+ def foo(o: Option[Int]): Int = {
+ lazy val i: Int = {
+ def local: Int = {if ("".isEmpty) return 42; -42}
+ assert(local == 42)
+ o.getOrElse(return -1)
+ }
+ i + 1
+ }
+
+ def main(args: Array[String]) {
+ assert(foo(None) == -1)
+ }
+}