From 3df1d77fc984b976efa68098206e801cf3b83a9e Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 16 Aug 2013 14:18:20 +0200 Subject: 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. --- .../scala/tools/nsc/typechecker/RefChecks.scala | 35 +++++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 1b6963b598..30b923e2a1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -113,6 +113,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 @@ -1667,19 +1672,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) - 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: + // val x2: List[_] = (x1.asInstanceOf[List[_]]: List[_]); + // matchEnd4({ x2; x2.reverse}) // case body is an argument to a label apply. + inPattern = false + super.transform(result) + } case _ => super.transform(result) } -- cgit v1.2.3