@@ -109,6 +109,60 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
109
109
private final val InterpolatorCodeRegex = """ \$\{\s*(.*?)\s*\}""" .r
110
110
private final val InterpolatorIdentRegex = """ \$[$\w]+""" .r // note that \w doesn't include $
111
111
112
+ abstract sealed class CheckDead {
113
+ def apply (tree : Tree ): Tree
114
+ @ inline final def updateExpr [A ](fn : Tree )(f : => A ): A = {
115
+ if (push(fn)) {
116
+ try f finally pop()
117
+ } else f
118
+ }
119
+ def push (fn : Tree ): Boolean
120
+ def pop (): Unit
121
+ def inMode (mode : Mode , tree : Tree ): Tree
122
+ }
123
+ object NoOpCheckDead extends CheckDead {
124
+ def apply (tree : Tree ): Tree = tree
125
+ def push (fn : Tree ): Boolean = false
126
+ def pop (): Unit = ()
127
+ def inMode (mode : Mode , tree : Tree ): Tree = tree
128
+ }
129
+ class CheckingCheckDead () extends CheckDead {
130
+ private val exprStack : mutable.Stack [Symbol ] = mutable.Stack (NoSymbol )
131
+ // The method being applied to `tree` when `apply` is called.
132
+ private def expr = exprStack.top
133
+
134
+ private def exprOK =
135
+ (expr != Object_synchronized ) &&
136
+ ! (expr.isLabel && treeInfo.isSynthCaseSymbol(expr)) // it's okay to jump to matchEnd (or another case) with an argument of type nothing
137
+
138
+ private def treeOK (tree : Tree ) = {
139
+ val isLabelDef = tree match { case _ : LabelDef => true ; case _ => false }
140
+ tree.tpe != null && tree.tpe.typeSymbol == NothingClass && ! isLabelDef
141
+ }
142
+
143
+ def push (fn : Tree ): Boolean = {
144
+ if (fn.symbol != null && fn.symbol.isMethod && ! fn.symbol.isConstructor) {
145
+ exprStack push fn.symbol
146
+ true
147
+ } else false
148
+ }
149
+ def pop (): Unit =
150
+ exprStack.pop()
151
+
152
+ def apply (tree : Tree ): Tree = {
153
+ // Error suppression (in context.warning) would squash some of these warnings.
154
+ // It is presumed if you are using a -Y option you would really like to hear
155
+ // the warnings you've requested; thus, use reporter.warning.
156
+ if (treeOK(tree) && exprOK)
157
+ reporter.warning(tree.pos, " dead code following this construct" )
158
+ tree
159
+ }
160
+
161
+ // The checkDead call from typedArg is more selective.
162
+ def inMode (mode : Mode , tree : Tree ): Tree = if (mode.typingMonoExprByValue) apply(tree) else tree
163
+ }
164
+
165
+
112
166
abstract class Typer (context0 : Context ) extends TyperDiagnostics with Adaptation with Tag with PatternTyper with TyperContextErrors {
113
167
import context0 .unit
114
168
import typeDebug .ptTree
@@ -253,6 +307,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
253
307
254
308
var context = context0
255
309
def context1 = context
310
+ private val checkDead : CheckDead = if (settings.warnDeadCode.value && context != null && context.unit.exists) new CheckingCheckDead () else NoOpCheckDead
256
311
257
312
// for use with silent type checking to when we can't have results with undetermined type params
258
313
// note that this captures the context var
0 commit comments