diff --git a/docs/_docs/reference/dropped-features/nonlocal-returns.md b/docs/_docs/reference/dropped-features/nonlocal-returns.md index e6490b7ca5bc..b7dae17f5a77 100644 --- a/docs/_docs/reference/dropped-features/nonlocal-returns.md +++ b/docs/_docs/reference/dropped-features/nonlocal-returns.md @@ -5,7 +5,7 @@ title: "Deprecated: Nonlocal Returns" nightlyOf: https://docs.scala-lang.org/scala3/reference/dropped-features/nonlocal-returns.html --- -Returning from nested anonymous functions has been deprecated, and will produce a warning from version `3.2`. +Returning from nested anonymous functions is deprecated since Scala 3.2.0. Nonlocal returns are implemented by throwing and catching `scala.runtime.NonLocalReturnException`-s. This is rarely what is intended by the programmer. It can be problematic because of the hidden performance cost of throwing and catching exceptions. Furthermore, it is a leaky implementation: a catch-all exception handler can intercept a `NonLocalReturnException`. @@ -21,5 +21,3 @@ def firstIndex[T](xs: List[T], elem: T): Int = if x == elem then break(i) -1 ``` - -Note: compiler produces deprecation error on nonlocal returns only with `-source:future` option. diff --git a/docs/_spec/06-expressions.md b/docs/_spec/06-expressions.md index ceb7dc4c36e5..c3ddcdfcd1ff 100644 --- a/docs/_spec/06-expressions.md +++ b/docs/_spec/06-expressions.md @@ -843,7 +843,11 @@ The type of a return expression is `scala.Nothing`. The expression ´e´ may be omitted. The return expression `return` is type-checked and evaluated as if it were `return ()`. -Returning from the method from within a nested function may be implemented by throwing and catching a `scala.runtime.NonLocalReturnControl`. +### Non-Local Returns (deprecated) + +Returning from a method from within a nested function is deprecated. + +It is implemented by throwing and catching a `scala.runtime.NonLocalReturnControl`. Any exception catches between the point of return and the enclosing methods might see and catch that exception. A key comparison makes sure that this exception is only caught by the method instance which is terminated by the return. diff --git a/docs/_spec/APPLIEDreference/dropped-features/nonlocal-returns.md b/docs/_spec/APPLIEDreference/dropped-features/nonlocal-returns.md new file mode 100644 index 000000000000..b7dae17f5a77 --- /dev/null +++ b/docs/_spec/APPLIEDreference/dropped-features/nonlocal-returns.md @@ -0,0 +1,23 @@ +--- +layout: doc-page +title: "Deprecated: Nonlocal Returns" + +nightlyOf: https://docs.scala-lang.org/scala3/reference/dropped-features/nonlocal-returns.html +--- + +Returning from nested anonymous functions is deprecated since Scala 3.2.0. + +Nonlocal returns are implemented by throwing and catching `scala.runtime.NonLocalReturnException`-s. This is rarely what is intended by the programmer. It can be problematic because of the hidden performance cost of throwing and catching exceptions. Furthermore, it is a leaky implementation: a catch-all exception handler can intercept a `NonLocalReturnException`. + +A better alternative to nonlocal returns and also the `scala.util.control.Breaks` API is provided by [`scala.util.boundary` and `boundary.break`](http://dotty.epfl.ch/api/scala/util/boundary$.html). + +Example: + +```scala +import scala.util.boundary, boundary.break +def firstIndex[T](xs: List[T], elem: T): Int = + boundary: + for (x, i) <- xs.zipWithIndex do + if x == elem then break(i) + -1 +``` diff --git a/docs/_spec/TODOreference/dropped-features/nonlocal-returns.md b/docs/_spec/TODOreference/dropped-features/nonlocal-returns.md deleted file mode 100644 index 17b86f77ee56..000000000000 --- a/docs/_spec/TODOreference/dropped-features/nonlocal-returns.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: doc-page -title: "Deprecated: Nonlocal Returns" - -nightlyOf: https://docs.scala-lang.org/scala3/reference/dropped-features/nonlocal-returns.html ---- - -Returning from nested anonymous functions has been deprecated, and will produce a warning from version `3.2`. - -Nonlocal returns are implemented by throwing and catching `scala.runtime.NonLocalReturnException`-s. This is rarely what is intended by the programmer. It can be problematic because of the hidden performance cost of throwing and catching exceptions. Furthermore, it is a leaky implementation: a catch-all exception handler can intercept a `NonLocalReturnException`. - -A drop-in library replacement is provided in [`scala.util.control.NonLocalReturns`](https://scala-lang.org/api/3.x/scala/util/control/NonLocalReturns$.html). Example: - -```scala -import scala.util.control.NonLocalReturns.* - -extension [T](xs: List[T]) - def has(elem: T): Boolean = returning { - for x <- xs do - if x == elem then throwReturn(true) - false - } - -@main def test(): Unit = - val xs = List(1, 2, 3, 4, 5) - assert(xs.has(2) == xs.contains(2)) -``` - -Note: compiler produces deprecation error on nonlocal returns only with `-source:future` option.