summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-08-16 14:18:20 +0200
committerJason Zaugg <jzaugg@gmail.com>2014-09-23 16:27:33 +1000
commit0022dccfde2f2d1e383254d8b5677c2468b57701 (patch)
tree70e0fa624cebc58e268aaacb6a7da3417721af15
parent5720e97b95da57c9549698a9038efb79092394ad (diff)
downloadscala-0022dccfde2f2d1e383254d8b5677c2468b57701.tar.gz
scala-0022dccfde2f2d1e383254d8b5677c2468b57701.tar.bz2
scala-0022dccfde2f2d1e383254d8b5677c2468b57701.zip
[backport] SI-7756 Uncripple refchecks in case bodies
In 65340ed4ad2e, parts of RefChecks were disabled when we traversed into the results of the new pattern matcher. Similar logic existed for the old pattern matcher, but in that case the Match / CaseDef nodes still existed in the tree. The new approach was too broad: important checks no longer scrutinized the body of cases. This commit turns the checks back on when it finds the remnants of a case body, which appears as an application to a label def. Conflicts: src/compiler/scala/tools/nsc/typechecker/RefChecks.scala Cherry pick of 3df1d77fc984b976efa68098206e801cf3b83a9e
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala35
-rw-r--r--test/files/neg/t7756a.check7
-rw-r--r--test/files/neg/t7756a.flags1
-rw-r--r--test/files/neg/t7756a.scala11
-rw-r--r--test/files/neg/t7756b.check4
-rw-r--r--test/files/neg/t7756b.flags1
-rw-r--r--test/files/neg/t7756b.scala5
-rw-r--r--test/files/pos/t7756b.scala13
8 files changed, 69 insertions, 8 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index fea234dd14..1d5a37eb38 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -98,6 +98,11 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
var localTyper: analyzer.Typer = typer;
var currentApplication: Tree = EmptyTree
var inPattern: Boolean = false
+ @inline final def savingInPattern[A](body: => A): A = {
+ val saved = inPattern
+ try body finally inPattern = saved
+ }
+
var checkedCombinations = Set[List[Type]]()
// only one overloaded alternative is allowed to define default arguments
@@ -1822,19 +1827,33 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
case _ => tree
}
+
// skip refchecks in patterns....
result = result match {
case CaseDef(pat, guard, body) =>
- inPattern = true
- val pat1 = transform(pat)
- inPattern = false
+ val pat1 = savingInPattern {
+ inPattern = true
+ transform(pat)
+ }
treeCopy.CaseDef(tree, pat1, transform(guard), transform(body))
case LabelDef(_, _, _) if treeInfo.hasSynthCaseSymbol(result) =>
- val old = inPattern
- inPattern = true
- val res = deriveLabelDef(result)(transform) // TODO SI-7756 Too broad! The code from the original case body should be fully refchecked!
- inPattern = old
- res
+ savingInPattern {
+ inPattern = true
+ deriveLabelDef(result)(transform)
+ }
+ case Apply(fun, args) if fun.symbol.isLabel && treeInfo.isSynthCaseSymbol(fun.symbol) =>
+ savingInPattern {
+ // SI-7756 If we were in a translated pattern, we can now switch out of pattern mode, as the label apply signals
+ // that we are in the user-supplied code in the case body.
+ //
+ // Relies on the translation of:
+ // (null: Any) match { case x: List[_] => x; x.reverse; case _ => }'
+ // to:
+ // <synthetic> val x2: List[_] = (x1.asInstanceOf[List[_]]: List[_]);
+ // matchEnd4({ x2; x2.reverse}) // case body is an argument to a label apply.
+ if (settings.future.value) inPattern = false // By default, bug compatibility with 2.10.[0-4]
+ super.transform(result)
+ }
case ValDef(_, _, _, _) if treeInfo.hasSynthCaseSymbol(result) =>
deriveValDef(result)(transform) // SI-7716 Don't refcheck the tpt of the synthetic val that holds the selector.
case _ =>
diff --git a/test/files/neg/t7756a.check b/test/files/neg/t7756a.check
new file mode 100644
index 0000000000..8d42717e47
--- /dev/null
+++ b/test/files/neg/t7756a.check
@@ -0,0 +1,7 @@
+t7756a.scala:7: error: type arguments [Object] do not conform to trait TA's type parameter bounds [X <: CharSequence]
+ locally(null: TA[Object])
+ ^
+t7756a.scala:7: error: type arguments [Object] do not conform to trait TA's type parameter bounds [X <: CharSequence]
+ locally(null: TA[Object])
+ ^
+two errors found
diff --git a/test/files/neg/t7756a.flags b/test/files/neg/t7756a.flags
new file mode 100644
index 0000000000..29f4ede37a
--- /dev/null
+++ b/test/files/neg/t7756a.flags
@@ -0,0 +1 @@
+-Xfuture
diff --git a/test/files/neg/t7756a.scala b/test/files/neg/t7756a.scala
new file mode 100644
index 0000000000..4453e84963
--- /dev/null
+++ b/test/files/neg/t7756a.scala
@@ -0,0 +1,11 @@
+object Test {
+ def test: Unit = {
+ trait TA[X <: CharSequence]
+ 0 match {
+ case _ =>
+ // the bounds violation isn't reported. RefChecks seems to be too broadly disabled under virtpatmat: see 65340ed4ad2e
+ locally(null: TA[Object])
+ ()
+ }
+ }
+}
diff --git a/test/files/neg/t7756b.check b/test/files/neg/t7756b.check
new file mode 100644
index 0000000000..5a88ae3c25
--- /dev/null
+++ b/test/files/neg/t7756b.check
@@ -0,0 +1,4 @@
+t7756b.scala:3: error: comparing values of types Int and String using `==' will always yield false
+ case _ => 0 == ""
+ ^
+one error found
diff --git a/test/files/neg/t7756b.flags b/test/files/neg/t7756b.flags
new file mode 100644
index 0000000000..3f3381a45b
--- /dev/null
+++ b/test/files/neg/t7756b.flags
@@ -0,0 +1 @@
+-Xfuture -Xfatal-warnings
diff --git a/test/files/neg/t7756b.scala b/test/files/neg/t7756b.scala
new file mode 100644
index 0000000000..a2de29c8e7
--- /dev/null
+++ b/test/files/neg/t7756b.scala
@@ -0,0 +1,5 @@
+object Test {
+ 0 match {
+ case _ => 0 == ""
+ }
+}
diff --git a/test/files/pos/t7756b.scala b/test/files/pos/t7756b.scala
new file mode 100644
index 0000000000..009248510d
--- /dev/null
+++ b/test/files/pos/t7756b.scala
@@ -0,0 +1,13 @@
+// This is a pos test to show that the backported bug fix for SI-7756 is
+// only enabled under -Xfuture.
+object Test {
+ def test: Unit = {
+ trait TA[X <: CharSequence]
+ 0 match {
+ case _ =>
+ // the bounds violation isn't reported. RefChecks seems to be too broadly disabled under virtpatmat: see 65340ed4ad2e
+ locally(null: TA[Object])
+ ()
+ }
+ }
+}