summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2014-09-24 00:20:40 +0200
committerGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2014-09-24 00:20:40 +0200
commita908ded364a6f8b664c6b02552a909c143d21b19 (patch)
tree1ca43c96e57a7420b08029d873e477cc80e5fe67
parent9ecfac84be3368acfd882d517c8138481b5568ec (diff)
parent0022dccfde2f2d1e383254d8b5677c2468b57701 (diff)
downloadscala-a908ded364a6f8b664c6b02552a909c143d21b19.tar.gz
scala-a908ded364a6f8b664c6b02552a909c143d21b19.tar.bz2
scala-a908ded364a6f8b664c6b02552a909c143d21b19.zip
Merge pull request #3998 from retronym/backport/7756
[backport] SI-7756 Uncripple refchecks in case bodies
-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])
+ ()
+ }
+ }
+}