Skip to content

Conversation

@NthPortal
Copy link
Contributor

@NthPortal NthPortal commented Feb 18, 2025

In scala.util.Using, when two exceptions are thrown, one is attached to the other using addSuppressed
according to a specified order.

Change that order to have scala.util.control.ControlThrowable suppressed by non-fatal exceptions (scala.util.control.NonFatal).

Fixes scala/bug#13088

Users of scala-collection-compat can upgrade to 2.14.0 to get the same behavior change

If you use Using in a project that crossbuilds to Scala 3, you may wish to wait for a Scala 3 release that includes the 2.13.17 standard library, or use a dependency override to force the upgrade in your build

@NthPortal NthPortal added the library:base Changes to the base library, i.e. Function Tuples Try label Feb 18, 2025
@scala-jenkins scala-jenkins added this to the 2.13.17 milestone Feb 18, 2025
@som-snytt
Copy link
Contributor

Probably you didn't anticipate such far-reaching effects!

java.io.IOException: No space left on device
	at java.base/java.io.FileOutputStream.writeBytes(Native Method)
***
	at java.base/java.lang.Thread.run(Thread.java:1583)
ERROR: Maximum checkout retry attempts reached, aborting

@lrytz
Copy link
Member

lrytz commented Feb 18, 2025

I'll fix Jenkins. GHA says

Test run scala.util.UsingTest finished: 4 failed

@lrytz
Copy link
Member

lrytz commented Feb 18, 2025

Here's an example that changes semantics. Is that a good change?

Before:

scala> def h(s: String): Unit = throw new RuntimeException
scala> def t: Int = util.Using.resource("hai")(s => return 42)(h)
scala> t
val res0: Int = 42

After:

...
scala> t
java.lang.RuntimeException
  at h(<console>:1)
  at $anonfun$t$2(<console>:1)
  at scala.util.Using$.resource(Using.scala:304)
  at t(<console>:1)
  ... 30 elided
  Suppressed: scala.runtime.NonLocalReturnControl$mcI$sp

@som-snytt I don't follow your mUsings around Odersky's Rule and the Titanic, I'm afraid..

@NthPortal
Copy link
Contributor Author

NthPortal commented Feb 18, 2025

Is that a good change?

I would argue that not only is it a good change, it is a correct change. before the change, where did the RuntimeException go? did we not close the resource? was it eaten by a grue? we've somehow returned normally without handling the exception. after this change, the exception when closing the resource propagates as it should (and would if Using was language syntax like try-with-resources is and not just a regular method).

I'll have a look at the failing tests Soon™. I admittedly did not run them locally, and just kinda assumed I adjusted them correctly

@som-snytt
Copy link
Contributor

In the example, we want the happy path.

If I want to "handle all the possibilities", then I have to catch all the possible aborts.

The answer for Future is use UEH so exceptions don't "disappear".

@lrytz
Copy link
Member

lrytz commented Feb 18, 2025

Java:

jshell> public int f() throws Exception { try (Closeable c = () -> { throw new RuntimeException(); }) { return 42; } }
|  modified method f()

jshell> f()
|  Exception java.lang.RuntimeException
|        at lambda$f$0 (#3:1)
|        at f (#3:1)
|        at (#4:1)

@som-snytt
Copy link
Contributor

The Odersky Rule is promulgated at
scala/scala3#17737 (comment)

@som-snytt
Copy link
Contributor

scala> :pa -java
// Entering paste mode (ctrl-D to finish)

package j;
import java.io.Closeable;
public class C {
public int f() throws Exception { try (Closeable c = () -> { throw new RuntimeException(); }) { return 42; } }
}

// Exiting paste mode... now compiling with javac.

scala> new j.C().f()
java.lang.RuntimeException
  at j.C.lambda$f$0(C.java:4)
  at j.C.f(C.java:4)
  ... 30 elided

scala>

Ergonomics in repl could be improved.

@Ichoran
Copy link
Contributor

Ichoran commented Feb 18, 2025

The new behavior is correct, I think: if you throw an exception while closing the resource, you did not successfully use the resource.

However, non-local return is deprecated, and boundary throws a RuntimeException which is eaten by Try so to be consistently forgiving of people who let control flow escape their threads, Using needs to (and does) catch that one too, which makes any change to ControlThrowable-handling a matter of backwards compatibility only: there's no real purpose to ControlThrowable any longer, and code would run faster if we deprecate and eliminate it.

Therefore, I am not convinced that there's much benefit to changing Using in this way. The existing way is arguably wrong, but there shouldn't be much future for it, and someone may have relied upon returns working even if closing mucked up in ordinary ways. On the other hand, the danger of changing behavior in unpleasantly also seems modest.

@lrytz
Copy link
Member

lrytz commented Feb 19, 2025

... so we cannot fix Using for boundary / break?

@NthPortal
Copy link
Contributor Author

so we cannot fix Using for boundary / break?

personally, I think this PR is a bug fix. the previous/current behaviour is wrong I believe because I (and everyone else) didn't think about it particularly hard past "fatal should have priority", not because we explicitly decided that ControlThrowable specifically ought to have priority over non-fatal exceptions.

also, sorry for taking so long to fix the tests. life happened at me

@Ichoran
Copy link
Contributor

Ichoran commented Apr 2, 2025

... so we cannot fix Using for boundary / break?

We could (by intercepting the type of exception that they throw and handling them specially), but since boundary/break control flow can't get through Try by design (we had long arguments about that, and the side I favored lost)--then Using should eat it also for consistency. That way you just remember that standard library exception-handling stuff eats control flow.

And then if you want exception handling that allows control flow to cross, you use a library for that.

@NthPortal
Copy link
Contributor Author

I don't think this PR changes anything meaningful wrt boundary/break given that it throws a RuntimeException

@lrytz
Copy link
Member

lrytz commented Apr 3, 2025

since boundary/break control flow can't get through Try by design (we had long arguments about that, and the side I favored lost)--then Using should eat it also for consistency. That way you just remember that standard library exception-handling stuff eats control flow.

Thanks, that makes sense :-/

Change `scala.util.Using` to have
`scala.util.control.ControlThrowable` be suppressed by non-fatal
exceptions (`scala.util.control.NonFatal`).
@NthPortal
Copy link
Contributor Author

thanks for squashing for me Lukas!

@lrytz lrytz merged commit 483b4ee into scala:2.13.x Apr 3, 2025
3 checks passed
@lrytz
Copy link
Member

lrytz commented Apr 3, 2025

Thank you for the work!

@SethTisue SethTisue added the release-notes worth highlighting in next release notes label Apr 3, 2025
@NthPortal NthPortal deleted the using-pref/PR branch April 4, 2025 00:47
hamzaremmal pushed a commit to hamzaremmal/scala3 that referenced this pull request May 2, 2025
hamzaremmal pushed a commit to scala/scala3 that referenced this pull request May 7, 2025
@lrytz lrytz changed the title Improve s.u.Using suppression order Improve scala.util.Using suppression order (NonFatal suppresses ControlThrowable) Sep 19, 2025
@SethTisue
Copy link
Member

ported to scala-collection-compat in scala/scala-collection-compat#712

mergify bot added a commit to slick/slick that referenced this pull request Oct 9, 2025
…n-compat to v2.14.0 (java17) (#3298)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
|
[org.scala-lang.modules:scala-collection-compat](http://www.scala-lang.org/)
([source](https://redirect.github.com/scala/scala-collection-compat)) |
minor | `2.13.0` -> `2.14.0` |

---

### Release Notes

<details>
<summary>scala/scala-collection-compat
(org.scala-lang.modules:scala-collection-compat)</summary>

###
[`v2.14.0`](https://redirect.github.com/scala/scala-collection-compat/releases/tag/v2.14.0):
2.14.0

[Compare
Source](https://redirect.github.com/scala/scala-collection-compat/compare/v2.13.0...v2.14.0)

Because the behavior of `Using` has changed, `Using` users should adopt
this release in tandem with upgrading to Scala 2.13.17.

If your crossbuild also includes Scala 3, then you may wish to also wait
for a Scala 3 release that has itself taken the upgrade to the 2.13.17
standard library, so your entire CI matrix will get the same behavior.

#### Breaking changes

- update `Using` from Scala 2.13.17 in
[#&#8203;712](https://redirect.github.com/scala/scala-collection-compat/pull/712)
- the behavior change is explained at
[scala/scala#11000](https://redirect.github.com/scala/scala/pull/11000)
by [@&#8203;NthPortal](https://redirect.github.com/NthPortal)

#### Chores

- update scala-native to 0.5.6 by
[@&#8203;xuwei-k](https://redirect.github.com/xuwei-k) in
[#&#8203;682](https://redirect.github.com/scala/scala-collection-compat/pull/682)
- Update sbt, scripted-plugin to 1.10.10 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;688](https://redirect.github.com/scala/scala-collection-compat/pull/688)
- Update sbt, scripted-plugin to 1.10.11 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;691](https://redirect.github.com/scala/scala-collection-compat/pull/691)
- Update sbt, scripted-plugin to 1.11.0 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;697](https://redirect.github.com/scala/scala-collection-compat/pull/697)
- Update sbt, scripted-plugin to 1.11.1 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;699](https://redirect.github.com/scala/scala-collection-compat/pull/699)
- Update sbt, scripted-plugin to 1.11.2 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;701](https://redirect.github.com/scala/scala-collection-compat/pull/701)
- Update sbt, scripted-plugin to 1.11.3 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;703](https://redirect.github.com/scala/scala-collection-compat/pull/703)
- Update sbt, scripted-plugin to 1.11.4 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;705](https://redirect.github.com/scala/scala-collection-compat/pull/705)
- Update sbt, scripted-plugin to 1.11.5 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;706](https://redirect.github.com/scala/scala-collection-compat/pull/706)
- Update sbt, scripted-plugin to 1.11.6 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;707](https://redirect.github.com/scala/scala-collection-compat/pull/707)
- Update sbt, scripted-plugin to 1.11.7 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;713](https://redirect.github.com/scala/scala-collection-compat/pull/713)
- Update sbt-scala-module to 3.3.0 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;700](https://redirect.github.com/scala/scala-collection-compat/pull/700)
- Update scala3-library\_sjs1 to 3.3.5 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;681](https://redirect.github.com/scala/scala-collection-compat/pull/681)
- Update scala3-library\_sjs1 to 3.3.6 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;696](https://redirect.github.com/scala/scala-collection-compat/pull/696)
- Update scalafmt-core to 3.9.0 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;683](https://redirect.github.com/scala/scala-collection-compat/pull/683)
- Update scalafmt-core to 3.9.1 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;685](https://redirect.github.com/scala/scala-collection-compat/pull/685)
- Update scalafmt-core to 3.9.10 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;708](https://redirect.github.com/scala/scala-collection-compat/pull/708)
- Update scalafmt-core to 3.9.2 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;686](https://redirect.github.com/scala/scala-collection-compat/pull/686)
- Update scalafmt-core to 3.9.3 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;689](https://redirect.github.com/scala/scala-collection-compat/pull/689)
- Update scalafmt-core to 3.9.4 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;690](https://redirect.github.com/scala/scala-collection-compat/pull/690)
- Update scalafmt-core to 3.9.5 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;693](https://redirect.github.com/scala/scala-collection-compat/pull/693)
- Update scalafmt-core to 3.9.6 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;694](https://redirect.github.com/scala/scala-collection-compat/pull/694)
- Update scalafmt-core to 3.9.7 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;698](https://redirect.github.com/scala/scala-collection-compat/pull/698)
- Update scalafmt-core to 3.9.8 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;702](https://redirect.github.com/scala/scala-collection-compat/pull/702)
- Update scalafmt-core to 3.9.9 by
[@&#8203;scala-steward](https://redirect.github.com/scala-steward) in
[#&#8203;704](https://redirect.github.com/scala/scala-collection-compat/pull/704)
- Add `dependabot.yml` for GitHub Actions update by
[@&#8203;xuwei-k](https://redirect.github.com/xuwei-k) in
[#&#8203;709](https://redirect.github.com/scala/scala-collection-compat/pull/709)
- Bump actions/checkout from 2 to 5 by
[@&#8203;dependabot](https://redirect.github.com/dependabot)\[bot] in
[#&#8203;711](https://redirect.github.com/scala/scala-collection-compat/pull/711)
- Bump actions/setup-java from 2 to 5 by
[@&#8203;dependabot](https://redirect.github.com/dependabot)\[bot] in
[#&#8203;710](https://redirect.github.com/scala/scala-collection-compat/pull/710)
- readme tweaks by
[@&#8203;SethTisue](https://redirect.github.com/SethTisue) in
[#&#8203;680](https://redirect.github.com/scala/scala-collection-compat/pull/680)

#### New Contributors

- [@&#8203;dependabot](https://redirect.github.com/dependabot)\[bot]
made their first contribution in
[#&#8203;710](https://redirect.github.com/scala/scala-collection-compat/pull/710)

**Full Changelog**:
<scala/scala-collection-compat@v2.13.0...v2.14.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/slick/slick).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNDMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE0My4xIiwidGFyZ2V0QnJhbmNoIjoiamF2YTE3IiwibGFiZWxzIjpbXX0=-->
dongjoon-hyun pushed a commit to apache/spark that referenced this pull request Oct 13, 2025
### What changes were proposed in this pull request?
Upgrade to scala 2.13.17

### Why are the changes needed?
To bring the latest bug fixes and improvements like JDK 25 support. Note that Scala community announces two breaking changes due to the bug fixes.

> Breaking changes
> - Mix in the productPrefix hash statically in case class hashCode
> - Improve scala.util.Using suppression order

- https://github.com/scala/scala/releases/tag/v2.13.17
  - scala/scala#11046
  - scala/scala#10937
  - scala/scala#10927
    - scala/bug#13058
  - scala/scala#11023
    - scala/bug#13033
  - scala/scala#11000

### Does this PR introduce _any_ user-facing change?
No

### How was this patch tested?
local and github builds

### Was this patch authored or co-authored using generative AI tooling?
No

Closes #52509 from vrozov/SPARK-53585.

Authored-by: Vlad Rozov <[email protected]>
Signed-off-by: Dongjoon Hyun <[email protected]>
huangxiaopingRD pushed a commit to huangxiaopingRD/spark that referenced this pull request Nov 25, 2025
### What changes were proposed in this pull request?
Upgrade to scala 2.13.17

### Why are the changes needed?
To bring the latest bug fixes and improvements like JDK 25 support. Note that Scala community announces two breaking changes due to the bug fixes.

> Breaking changes
> - Mix in the productPrefix hash statically in case class hashCode
> - Improve scala.util.Using suppression order

- https://github.com/scala/scala/releases/tag/v2.13.17
  - scala/scala#11046
  - scala/scala#10937
  - scala/scala#10927
    - scala/bug#13058
  - scala/scala#11023
    - scala/bug#13033
  - scala/scala#11000

### Does this PR introduce _any_ user-facing change?
No

### How was this patch tested?
local and github builds

### Was this patch authored or co-authored using generative AI tooling?
No

Closes apache#52509 from vrozov/SPARK-53585.

Authored-by: Vlad Rozov <[email protected]>
Signed-off-by: Dongjoon Hyun <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

library:base Changes to the base library, i.e. Function Tuples Try release-notes worth highlighting in next release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect/unreasonable suppression behavior of s.u.Using

6 participants