Skip to content

Commit

Permalink
[backport] SI-7756 Uncripple refchecks in case bodies
Browse files Browse the repository at this point in the history
In 65340ed, 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 3df1d77
  • Loading branch information
retronym committed Sep 23, 2014
1 parent 5720e97 commit 0022dcc
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 8 deletions.
35 changes: 27 additions & 8 deletions src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
Expand Up @@ -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
Expand Down Expand Up @@ -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 _ =>
Expand Down
7 changes: 7 additions & 0 deletions 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
1 change: 1 addition & 0 deletions test/files/neg/t7756a.flags
@@ -0,0 +1 @@
-Xfuture
11 changes: 11 additions & 0 deletions 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])
()
}
}
}
4 changes: 4 additions & 0 deletions 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
1 change: 1 addition & 0 deletions test/files/neg/t7756b.flags
@@ -0,0 +1 @@
-Xfuture -Xfatal-warnings
5 changes: 5 additions & 0 deletions test/files/neg/t7756b.scala
@@ -0,0 +1,5 @@
object Test {
0 match {
case _ => 0 == ""
}
}
13 changes: 13 additions & 0 deletions 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])
()
}
}
}

0 comments on commit 0022dcc

Please sign in to comment.