Skip to content

Commit 3bd718d

Browse files
committed
Xlint nonlocal-return
Don't just log it, Xlint it! Mention where control is returning to.
1 parent e1d4216 commit 3bd718d

File tree

5 files changed

+23
-0
lines changed

5 files changed

+23
-0
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ trait Warnings {
103103
val StarsAlign = LintWarning("stars-align", "Pattern sequence wildcard must align with sequence component.")
104104
val Constant = LintWarning("constant", "Evaluation of a constant arithmetic expression results in an error.")
105105
val Unused = LintWarning("unused", "Enable -Ywarn-unused:imports,privates,locals,implicits.")
106+
val NonlocalReturn = LintWarning("nonlocal-return", "A return statement used an exception for flow control.")
106107

107108
def allLintWarnings = values.toSeq.asInstanceOf[Seq[LintWarning]]
108109
}
@@ -126,6 +127,7 @@ trait Warnings {
126127
def warnStarsAlign = lint contains StarsAlign
127128
def warnConstant = lint contains Constant
128129
def lintUnused = lint contains Unused
130+
def warnNonlocalReturn = lint contains NonlocalReturn
129131

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

src/compiler/scala/tools/nsc/transform/UnCurry.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,8 @@ abstract class UnCurry extends InfoTransform
623623
applyUnary()
624624
case ret @ Return(expr) if isNonLocalReturn(ret) =>
625625
log(s"non-local return from ${currentOwner.enclMethod} to ${ret.symbol}")
626+
if (settings.warnNonlocalReturn)
627+
reporter.warning(ret.pos, s"return statement uses an exception to pass control to the caller of the enclosing named ${ret.symbol}")
626628
atPos(ret.pos)(nonLocalReturnThrow(expr, ret.symbol))
627629
case TypeTree() =>
628630
tree

test/files/neg/t10820-warn.check

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
t10820-warn.scala:11: warning: return statement uses an exception to pass control to the caller of the enclosing named method result
2+
def result: Option[Int] = Try(0/0).recoverWith { case _ => return Some(-1) }.toOption
3+
^
4+
error: No warnings can be incurred under -Xfatal-warnings.
5+
one warning found
6+
one error found

test/files/neg/t10820-warn.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Xfatal-warnings -Xlint:nonlocal-return

test/files/neg/t10820-warn.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
import util.Try
3+
4+
trait Test {
5+
6+
/*
7+
* Inspired by
8+
* https://stackoverflow.com/questions/50297478/why-scala-allows-return-from-recoverwith
9+
* "I actually saw the post Don't Use Return in Scala long ago never paid attention."
10+
*/
11+
def result: Option[Int] = Try(0/0).recoverWith { case _ => return Some(-1) }.toOption
12+
}

0 commit comments

Comments
 (0)