Skip to content

Commit 1b1bc81

Browse files
lifflrytz
authored andcommitted
Emit a warning when a constant expression evaluates to an ArithmeticException (scala#5123)
1 parent 86fe7de commit 1b1bc81

File tree

5 files changed

+15
-7
lines changed

5 files changed

+15
-7
lines changed

src/compiler/scala/tools/nsc/settings/Warnings.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ trait Warnings {
5959
val PackageObjectClasses = LintWarning("package-object-classes", "Class or object defined in package object.")
6060
val UnsoundMatch = LintWarning("unsound-match", "Pattern match may not be typesafe.")
6161
val StarsAlign = LintWarning("stars-align", "Pattern sequence wildcard must align with sequence component.")
62+
val Constant = LintWarning("constant", "Evaluation of a constant arithmetic expression results in an error.")
6263

6364
def allLintWarnings = values.toSeq.asInstanceOf[Seq[LintWarning]]
6465
}
@@ -80,6 +81,7 @@ trait Warnings {
8081
def warnPackageObjectClasses = lint contains PackageObjectClasses
8182
def warnUnsoundMatch = lint contains UnsoundMatch
8283
def warnStarsAlign = lint contains StarsAlign
84+
def warnConstant = lint contains Constant
8385

8486
// Lint warnings that are currently -Y, but deprecated in that usage
8587
@deprecated("Use warnAdaptedArgs", since="2.11.2")

src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ abstract class ConstantFolder {
4040
if ((x ne null) && x.tag != UnitTag) tree setType ConstantType(x)
4141
else tree
4242
} catch {
43-
case _: ArithmeticException => tree // the code will crash at runtime,
44-
// but that is better than the
45-
// compiler itself crashing
43+
case e: ArithmeticException =>
44+
if (settings.warnConstant)
45+
warning(tree.pos, s"Evaluation of a constant expression results in an arithmetic error: ${e.getMessage}")
46+
tree
4647
}
4748

4849
private def foldUnop(op: Name, x: Constant): Constant = (op, x.tag) match {
@@ -158,7 +159,7 @@ abstract class ConstantFolder {
158159
else if (x.isNumeric && y.isNumeric) math.max(x.tag, y.tag)
159160
else NoTag
160161

161-
try optag match {
162+
optag match {
162163
case BooleanTag => foldBooleanOp(op, x, y)
163164
case ByteTag | ShortTag | CharTag | IntTag => foldSubrangeOp(op, x, y)
164165
case LongTag => foldLongOp(op, x, y)
@@ -167,8 +168,5 @@ abstract class ConstantFolder {
167168
case StringTag if op == nme.ADD => Constant(x.stringValue + y.stringValue)
168169
case _ => null
169170
}
170-
catch {
171-
case _: ArithmeticException => null
172-
}
173171
}
174172
}

test/files/pos/constant-warning.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
constant-warning.scala:2: warning: Evaluation of a constant expression results in an arithmetic error: / by zero
2+
val fails = 1 + 2 / (3 - 2 - 1)
3+
^
4+
one warning found

test/files/pos/constant-warning.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Xlint:constant

test/files/pos/constant-warning.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object Test {
2+
val fails = 1 + 2 / (3 - 2 - 1)
3+
}

0 commit comments

Comments
 (0)