summaryrefslogtreecommitdiff
path: root/test/files/run/t6070.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2012-07-12 16:46:25 +0200
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-07-17 23:37:39 +0200
commitaa6fa4623b54ed21b3246e4c98c720adbbac2473 (patch)
tree5aca9834be1ceafba31d03e1bc5923256e6f8247 /test/files/run/t6070.scala
parent4f07a12b3f4ce1595d4976123e5cfe34e186d4ba (diff)
downloadscala-aa6fa4623b54ed21b3246e4c98c720adbbac2473.tar.gz
scala-aa6fa4623b54ed21b3246e4c98c720adbbac2473.tar.bz2
scala-aa6fa4623b54ed21b3246e4c98c720adbbac2473.zip
SI-5739 store sub-patterns in local vals
Also closes SI-5158 (debuggability), SI-6070 (soundness). To improve both debuggability and soundness, we now store the result of an extractor (user-defined and synthetic) in local variables. For the case class case, this also fixes the soundness bug SI-6070, as this prevents post-match mutation of bound variables. The core of the refactoring consisted of introducing the PreserveSubPatBinders trait, which introduces local variables instead of substituting symbols for the RHS of those variables (so this can be seen as reverting the premature optimization of inline the case-class getters into the case body). Since TreeMakerToCond fuses the substitutions performed in a match to find out which symbolic values binders evaluate to, masquerade PreserveSubPatBinders's binding of subPatBinders and subPatRefs as the corresponding substitution. Consider `case class Foo(bar: Int)`, then `case y@Foo(x) => println(x)` gives rise to `{val x = y.bar; println(x)}` (instead of `println(y.bar)`), and `subPatternsAsSubstitution` pretends we still replace `x` by `y.bar`, instead of storing it in a local variable so that the rest of the analysis need not be modified. Misc notes: - correct type for seq-subpattern - more error resilience (ill-typed patterns sometimes slip past the typechecker -- reopened SI-4425) TODO: come up with a more abstract framework for expressing bound symbols and their values
Diffstat (limited to 'test/files/run/t6070.scala')
-rw-r--r--test/files/run/t6070.scala36
1 files changed, 36 insertions, 0 deletions
diff --git a/test/files/run/t6070.scala b/test/files/run/t6070.scala
new file mode 100644
index 0000000000..b6af48ef21
--- /dev/null
+++ b/test/files/run/t6070.scala
@@ -0,0 +1,36 @@
+abstract class Bomb {
+ type T
+ val x: T
+
+ def size(that: T): Int
+}
+
+class StringBomb extends Bomb {
+ type T = String
+ val x = "abc"
+ def size(that: String): Int = that.length
+}
+
+class IntBomb extends Bomb {
+ type T = Int
+ val x = 10
+
+ def size(that: Int) = x + that
+}
+
+case class Mean(var bomb: Bomb)
+
+object Test extends App {
+ def foo(x: Mean) = x match {
+ case Mean(b) =>
+ // BUG: b is assumed to be a stable identifier, but it can actually be mutated
+ println(b.size({ mutate(); b.x }))
+ }
+
+ def mutate() {
+ m.bomb = new IntBomb
+ }
+
+ val m = Mean(new StringBomb)
+ foo(m) // should print 3
+} \ No newline at end of file