<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://www.scala-lang.org/</id>
  <title type="text" xml:lang="en">The Scala Programming Language</title>
  <link type="application/atom+xml" href="https://www.scala-lang.org/feed/index.xml" rel="self"/>
  <link type="text/html" href="https://www.scala-lang.org/news/" rel="alternate"/>

  <updated>2026-09-11T17:45:05+02:00</updated>
  <author>
    <name>École Polytechnique Fédérale de Lausanne</name>
  </author>
  <rights>Copyright (c) 2002-2026 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland</rights>

  
  <entry>
    <title>Scala 3.9 LTS released!</title>
    <link href="https://www.scala-lang.org/news/3.9/"/>
    <updated>2026-09-03T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/news/release-notes-3.9</id>
    <content type="html">&lt;h1 id=&quot;scala-39-lts-released&quot;&gt;Scala 3.9 LTS released!&lt;/h1&gt;

&lt;p&gt;We are happy to announce &lt;strong&gt;Scala 3.9.0&lt;/strong&gt;, opening the new &lt;strong&gt;Long Term Support&lt;/strong&gt; line for Scala 3.
It succeeds Scala 3.3 LTS as the recommended baseline for library authors and conservative production users, while keeping the Scala Next line available for teams that want the latest language work as soon as it is released.&lt;/p&gt;

&lt;h2 id=&quot;what-does-lts-mean&quot;&gt;What does LTS mean?&lt;/h2&gt;

&lt;p&gt;Scala 3 follows the &lt;a href=&quot;/blog/2022/08/17/long-term-compatibility-plans.html&quot;&gt;Scala LTS and Scala Next model&lt;/a&gt;.
&lt;strong&gt;Scala Next&lt;/strong&gt; receives regular minor releases with new language features, tooling work, and ecosystem changes.
&lt;strong&gt;Scala LTS&lt;/strong&gt; receives patch releases focused on bug fixes, diagnostics, tooling improvements, and carefully selected quality-of-life changes that are also subject to the compatibility guarantees of the LTS line.&lt;/p&gt;

&lt;p&gt;Libraries published with Scala 3.9 LTS can be consumed by later 3.9 patch releases and by Scala Next. The 3.9 line is expected to receive patches and backports for an extended period.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Library maintainers:&lt;/strong&gt; artifacts built with Scala 3.9 cannot be consumed by Scala 3.3 projects, so treat the move from Scala 3.3 LTS to Scala 3.9 LTS as a minor-version publishing decision for your own libraries.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;looking-back-at-scala-33-lts&quot;&gt;Looking back at Scala 3.3 LTS&lt;/h2&gt;

&lt;p&gt;Scala 3.3.0 was released in May 2023 and became the first Scala 3 LTS.
It carried the ecosystem through more than three years of Scala 3 development while Scala Next delivered new syntax, new standard-library work, new tooling integration, and deeper compatibility testing.&lt;/p&gt;

&lt;p&gt;The 3.3 LTS line was not a frozen branch. As I write this, &lt;strong&gt;1,420 of 2,380&lt;/strong&gt; pull requests merged into the main Scala 3 compiler branch since 3.4.0 were also backported to Scala 3.3 LTS. That’s almost &lt;strong&gt;43% of all changes&lt;/strong&gt;!
That work kept 3.3 useful as a publishing target while still protecting the compatibility expectations that made it attractive in the first place.
The result of this decision is visible in the ecosystem - roughly &lt;strong&gt;56% of Scala 3 libraries&lt;/strong&gt; are currently published using Scala 3.3 LTS.&lt;/p&gt;

&lt;p&gt;What’s more, the next patch release - &lt;strong&gt;Scala 3.3.9&lt;/strong&gt; - is planned within the next month, and Scala 3.3 LTS will remain actively maintained for &lt;strong&gt;one year after Scala 3.9.0&lt;/strong&gt;. However, the number of future backports is expected to be lower than before, as Scala 3.3 LTS and Scala Next codebases have naturally diverged after several years of development.
Special thanks go to Paweł Marks, Wojciech Mazur, and Tomasz Godzik from VirtusLab for the sustained backporting and maintenance work over the years!&lt;/p&gt;

&lt;h2 id=&quot;whats-new-in-scala-39&quot;&gt;What’s new in Scala 3.9?&lt;/h2&gt;

&lt;p&gt;Scala 3.9.0 is both a new LTS baseline and a regular Scala release.
It consolidates the changes since Scala 3.8, stabilises one language feature, and includes a broad set of compiler, standard-library, documentation, and tooling fixes.&lt;/p&gt;

&lt;h3 id=&quot;sip-71-allow-fully-implicit-conversions-in-scala-3-with-into---now-stable&quot;&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/71.html&quot;&gt;SIP-71: Allow fully implicit conversions in Scala 3 with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;into&lt;/code&gt;&lt;/a&gt; - now stable&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;into&lt;/code&gt; mechanism lets API authors mark selected parameters or types as accepting implicit conversions, without asking all users to enable implicit conversions globally.&lt;/p&gt;

&lt;p&gt;This is useful for APIs where conversion is part of the intended design, but where unrestricted implicit conversions would be too broad.
Scala 3.8 introduced &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;into&lt;/code&gt; as a preview feature; Scala 3.9 makes it part of the stable language.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using scala 3.9&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Prefer `into` as a soft modifier when you control the conversion target.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;into&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IntoIterableOnce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IterableOnce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;appendAll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ys&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;IntoIterableOnce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ys&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Use `into[T]` when you can&apos;t change the target type definition.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;prependAll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Conversion.into&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;IterableOnce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ys&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;toList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ys&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;given&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Conversion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;IntoIterableOnce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IntoIterableOnce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;iterator:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;iterator&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;given&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Conversion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;IterableOnce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;iterator&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;appended&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;appendAll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;prepended&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;prependAll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;documentation-snippets-can-declare-the-errors-they-expect&quot;&gt;Documentation snippets can declare the errors they expect&lt;/h3&gt;

&lt;p&gt;Scaladoc can compile the code snippets it finds in documentation, which stops examples from quietly rotting as a project changes.
Scala 3.9 allows a snippet &lt;a href=&quot;https://github.com/scala/scala3/pull/25713&quot;&gt;to also declare the errors and warnings it is meant to produce&lt;/a&gt;, on the exact lines where they belong.&lt;/p&gt;

&lt;p&gt;Documentation for a library with compile-time constraints often needs to show code that must not compile: a macro reporting a custom error, an API enforcing capability or capture requirements, or a type-level constraint being violated.
Until now such a snippet could only claim that it failed somewhere. There was no way to say which line should fail, or whether to expect an error or a warning.&lt;/p&gt;

&lt;p&gt;To switch the checks on, add the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; modifier to Scaladoc’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-snippet-compiler&lt;/code&gt; setting for the path you want covered:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Compile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scalacOptions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;-snippet-compiler:docs/my-page.md=compile+test&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The path is matched as a prefix, so it can just as well name a directory and cover a whole section of a site at once.
Expected diagnostics are then marked in the snippet itself, by putting an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;// error&lt;/code&gt; comment on the line that should fail:&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;```&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;scala
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;sum&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// error: List[String] is not a List[Int]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;```&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The rules are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A marker is matched on severity and line number only.
The text following it is not checked, so it can carry an explanation for readers.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;// warn&lt;/code&gt; checks warnings the same way.&lt;/li&gt;
  &lt;li&gt;Every diagnostic must be accounted for: an unmarked error or warning fails the run, and a snippet with no markers must compile cleanly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Snippets in Scaladoc comments are configured through the same path-based setting and honour the markers as well, but the intended use is documentation pages.
Snippets in comments written with the legacy wiki syntax are not checked at all, as before.&lt;/p&gt;

&lt;h3 id=&quot;scala-cli-updates&quot;&gt;Scala CLI updates&lt;/h3&gt;

&lt;p&gt;Scala 3.9 updates Scala CLI, which brings new features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The REPL can start &lt;strong&gt;JShell&lt;/strong&gt;, so a project’s classpath can be explored from Java as well as from Scala. Try it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala repl --jshell&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Tests can be written against &lt;strong&gt;JUnit 5 (Jupiter)&lt;/strong&gt;, not only the JUnit 4 interface shipped previously.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt; can target &lt;strong&gt;sbt 2.x&lt;/strong&gt;, allowing rapid conversion of a project to sbt.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;WebAssembly&lt;/strong&gt; is supported experimentally, matching the new Scala.js backend.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Ammonite&lt;/strong&gt; support has been dropped.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most consequential change for anyone moving to a recent JDK is experimental built-in support for &lt;strong&gt;&lt;a href=&quot;https://github.com/VirtusLab/sloth&quot;&gt;Sloth&lt;/a&gt;&lt;/strong&gt;.
Code compiled with Scala 3.0 to 3.7 emits &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lazy val&lt;/code&gt; bytecode that goes through the legacy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.runtime.LazyVals&lt;/code&gt; API.
That API is implemented with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sun.misc.Unsafe&lt;/code&gt;, which was terminally deprecated in JDK 24. Under JDK 26 it only prints a warning at runtime; once it is removed in a future JDK, the affected code stops working altogether.
Compiling with Scala 3.8 or later is not enough to escape this, because any dependency published with the old lazy vals brings the problem back.&lt;/p&gt;

&lt;p&gt;Sloth removes that risk by rewriting the bytecode of such dependencies to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VarHandle&lt;/code&gt;-based implementation introduced in Scala 3.8.
It can run ahead of time, as a post-processing step over the classpath, or just in time through a dedicated JVM agent.&lt;/p&gt;

&lt;p&gt;Both modes are opt-in, and the easiest way to reach for them is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt; directive:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using dep com.example::library-built-with-scala-3.3:1.0.0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using jvm 26&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using sloth&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@main&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Legacy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Writing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//&amp;gt; using slothAgent&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//&amp;gt; using sloth&lt;/code&gt; rewrites each class as it is loaded rather than patching the classpath up front, which is the more practical choice when running tests.&lt;/p&gt;

&lt;p&gt;The same options are available on the Scala runner, as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--sloth&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--sloth-agent&lt;/code&gt;.
In both cases the feature is experimental, so it has to be unlocked with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--power&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scala &lt;span class=&quot;nt&quot;&gt;--power&lt;/span&gt; run Main.scala &lt;span class=&quot;nt&quot;&gt;--sloth&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See the Scala CLI &lt;a href=&quot;https://github.com/VirtusLab/scala-cli/releases/tag/v1.15.0&quot;&gt;v1.15.0&lt;/a&gt; and &lt;a href=&quot;https://github.com/VirtusLab/scala-cli/releases/tag/v1.16.0&quot;&gt;v1.16.0&lt;/a&gt; release notes for the full list of changes.&lt;/p&gt;

&lt;p&gt;The parser for Scala CLI &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt; directives has moved into a compiler module &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.scala-lang::scala3-directives-parser:3.9.0&lt;/code&gt;.
This gives tools a shared implementation for parsing build and dependency directives in Scala source files and allows custom use outside of Scala CLI.&lt;/p&gt;

&lt;h3 id=&quot;scalajs-122&quot;&gt;Scala.js 1.22&lt;/h3&gt;

&lt;p&gt;Scala 3.9 ships with &lt;a href=&quot;https://www.scala-js.org/news/2026/06/20/announcing-scalajs-1.22.0/&quot;&gt;Scala.js 1.22.0&lt;/a&gt;.
The Scala.js backend is part of the compiler rather than a separate plugin, so this Scala.js minor is fixed for the whole 3.9 LTS line: a newer Scala.js minor needs a newer Scala minor.
Worth keeping in mind when upgrading: Scala.js 1.22 becomes the minimum version your downstream users need as well.&lt;/p&gt;

&lt;p&gt;The main feature of Scala.js 1.22 is a stable WebAssembly backend.
It targets a JavaScript host rather than standalone WebAssembly, so the output runs on Node.js, Deno, Bun, or a browser - not on a Wasm-only runtime.
It requires ECMAScript 2022 or newer, an engine implementing Wasm 3.0, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESModule&lt;/code&gt; module kind.
Those requirements are now the default Scala.js baseline. Node.js 25, Chrome 137, Firefox 134, and Safari 26 all meet them.&lt;/p&gt;

&lt;p&gt;Enable it in sbt by requesting ES modules, ECMAScript 2022, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESFeatures.withUseWebAssembly&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// build.sbt&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;scalaJSLinkerConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;scalaJSLinkerConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;value&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;withModuleKind&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ModuleKind&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;ESModule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;withESFeatures&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;withESVersion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ESVersion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;ES2022&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;withUseWebAssembly&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The equivalent for Scala CLI is two directives:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using wasm&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using jsModuleKind es&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@main&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello from Wasm!&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Wasm support in the Scala runner is experimental, so it has to be invoked with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--power&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scala &lt;span class=&quot;nt&quot;&gt;--power&lt;/span&gt; run HelloWasm.scala
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js.async&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js.await&lt;/code&gt; need one more step on Wasm: enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.withWasmFeatures(_.withUseJSPI(true))&lt;/code&gt; and run on an engine that supports JavaScript Promise Integration.
JSPI is standardised, but it is not part of Wasm 3.0, which is why it stays behind that opt-in.&lt;/p&gt;

&lt;p&gt;Other improvements in Scala.js 1.22:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Generated code is smaller:&lt;/strong&gt; the embedded Unicode database uses a tighter encoding, and the JavaScript backend now aggressively optimises arrays of numeric literals.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Unicode support&lt;/strong&gt; moved to Unicode 15.0, matching JDK 21. It now also accounts for contributory properties, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isLowerCase&lt;/code&gt; is true for characters carrying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Other_Lowercase&lt;/code&gt;, not only for those in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ll&lt;/code&gt; category.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;sbt 2.x:&lt;/strong&gt; if you are migrating, you will need this Scala.js version as well, since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt-scalajs&lt;/code&gt; is now published for sbt 2.x alongside sbt 1.x.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See the &lt;a href=&quot;https://www.scala-js.org/news/2026/06/20/announcing-scalajs-1.22.0/&quot;&gt;Scala.js 1.22.0 announcement&lt;/a&gt; for the full list, including bug fixes.&lt;/p&gt;

&lt;h3 id=&quot;inaccessible-companion-implicits-will-no-longer-be-found-in-scala-310&quot;&gt;Inaccessible companion implicits will no longer be found in Scala 3.10&lt;/h3&gt;

&lt;p&gt;When implicit search builds the implicit scope for a type, it looks into that type’s companion object.
Until now it did so even when the companion could not be referenced from the call site.
That gave call sites unexpected access to private implicits: the instance could be summoned implicitly, even though writing it out explicitly would not compile.
Scala 3.9 reports every such resolution as a warning under the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-deprecation&lt;/code&gt; flag, and Scala 3.10 &lt;a href=&quot;https://github.com/scala/scala3/pull/25367&quot;&gt;stops finding those instances altogether&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Config&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;given&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Config&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;configured&quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;describe&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// deprecation warning: usage of the implicit defined in object Config, which is not accessible&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// here; in Scala 3.10 this implicit will no longer be found&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The specification has always required an eligible implicit to be accessible at the point of the call, so this closes a hole rather than removing a feature.&lt;/p&gt;

&lt;p&gt;It is worth acting on now. Scala 3.9 only warns, but on 3.10 the same code fails to compile, and you usually cannot fix it in the consuming project: the instance lives in a library, so that library needs a new release to make it accessible.
The Open Community Build found around &lt;strong&gt;20 projects&lt;/strong&gt; that stop compiling on 3.10 for this reason.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;What to do:&lt;/strong&gt; compile with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-deprecation&lt;/code&gt; on Scala 3.9 to see these warnings in detail. If a library you maintain emits them, publish the fix before 3.10 arrives.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;other-notable-changes&quot;&gt;Other notable changes&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Java generic signatures are more accurate&lt;/strong&gt;, covering higher-kinded types, refined types, arrays of value classes, context functions, inherited inner classes, trait setters, and generic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt; parameters.&lt;/li&gt;
  &lt;li&gt;The standard-library JAR again declares &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Automatic-Module-Name&lt;/code&gt; in its manifest, which JPMS consumers need.&lt;/li&gt;
  &lt;li&gt;The &lt;strong&gt;standard library is now optimized&lt;/strong&gt; with the Scala backend optimizer.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Scoverage instrumentation&lt;/strong&gt; is more reliable, including around separation checking, tail recursion and infinite-loop warnings, constructor applications, singleton types, closures, and parameterless methods.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Incremental compilation&lt;/strong&gt; can now invalidate type arguments used in macro calls, so Zinc rebuilds those call sites when the argument types change.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Diagnostics and linting are tighter&lt;/strong&gt;: reports about missing members are more actionable, unused-variable warnings have fewer false positives, and easily misread syntax now warns, such as a template left empty after a trailing colon.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Scaladoc is lighter:&lt;/strong&gt; it no longer ships jQuery or custom fonts reducing size of published artifacts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full list is in the &lt;a href=&quot;https://github.com/scala/scala3/releases/tag/3.9.0&quot;&gt;Scala 3.9.0 release notes&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;coming-from-scala-33-lts&quot;&gt;Coming from Scala 3.3 LTS?&lt;/h2&gt;

&lt;p&gt;If you are moving directly from Scala 3.3 LTS to Scala 3.9 LTS, you are crossing five minor releases.
Most projects should still be able to migrate with little or no source work, but it is useful to know what changed along the way.
The sections below summarise the most important changes in each minor.&lt;/p&gt;

&lt;h3 id=&quot;scala-34&quot;&gt;&lt;a href=&quot;/blog/2024/02/29/scala-3.4.0-and-3.3.3-released.html&quot;&gt;Scala 3.4&lt;/a&gt;&lt;/h3&gt;

&lt;h4 id=&quot;new-stable-features&quot;&gt;New stable features&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/quote-pattern-type-variable-syntax.html&quot;&gt;SIP-53 Quote Pattern Type Variable Syntax&lt;/a&gt; - type patterns in quotes became more expressive, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case &apos;[ (t, t, t) ]&lt;/code&gt; matches a 3-element tuple whose elements all have the same type.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/multi-source-extension-overloads.html&quot;&gt;SIP-54 Multi-Source Extension Overloads&lt;/a&gt; - extension methods with the same name can be imported from different sources.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/match-types-spec.html&quot;&gt;SIP-56 Match Types Specification&lt;/a&gt; - match types are properly specified and behave predictably.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;breaking-changes&quot;&gt;Breaking changes&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/match-types-spec.html&quot;&gt;SIP-56 Match Types Specification&lt;/a&gt; - some previously accepted match types are no longer legal and need to be rewritten.&lt;/li&gt;
  &lt;li&gt;Legacy syntax started warning: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt; type wildcards, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;private[this]&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var x = _&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with&lt;/code&gt; as a type operator, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xs: _*&lt;/code&gt; varargs, and a trailing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt; to force eta expansion. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-rewrite -source:3.4-migration&lt;/code&gt; applies every rewrite, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.3&lt;/code&gt; silences the warnings instead.&lt;/li&gt;
  &lt;li&gt;Refutable patterns in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for&lt;/code&gt; generator now need an explicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.withFilter&lt;/code&gt; is no longer inserted without it.&lt;/li&gt;
  &lt;li&gt;Type inference changed for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inline&lt;/code&gt; methods, which can break call sites.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;other-notable-changes-1&quot;&gt;Other notable changes&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Inference for fold-like calls improved, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xs.foldRight((Nil, Nil))(...)&lt;/code&gt; no longer needs explicit types.&lt;/li&gt;
  &lt;li&gt;Polymorphic lambdas can omit their parameter types when those are inferable from the context.&lt;/li&gt;
  &lt;li&gt;The compiler no longer synthesizes given definitions that can cycle back to themselves.&lt;/li&gt;
  &lt;li&gt;Polymorphic lambdas compile to JVM lambdas instead of anonymous classes.&lt;/li&gt;
  &lt;li&gt;The JVM backend gained the parallelization ported from Scala 2.&lt;/li&gt;
  &lt;li&gt;Errors for incompatible TASTy versions and broken class files became readable and actionable.&lt;/li&gt;
  &lt;li&gt;Diagnostics, including unused warnings, are exported to SemanticDB.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;scala-35&quot;&gt;&lt;a href=&quot;/blog/2024/08/22/scala-3.5.0-released.html&quot;&gt;Scala 3.5&lt;/a&gt;&lt;/h3&gt;

&lt;h4 id=&quot;notable-changes&quot;&gt;Notable changes&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala&lt;/code&gt; command itself became the Scala runner, implemented by &lt;a href=&quot;https://scala-cli.virtuslab.org/&quot;&gt;Scala CLI&lt;/a&gt;, so it now compiles, runs, tests, and packages single-module projects.&lt;/li&gt;
  &lt;li&gt;Experimental best-effort compilation emits BETASTy for code that does not compile, which keeps IDE features working while you type.&lt;/li&gt;
  &lt;li&gt;Pipelined builds are supported, enabled in sbt with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThisBuild / usePipelining := true&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var&lt;/code&gt; members are allowed in type refinements, as in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type A = { var number: Int }&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Integer literals can be written in base 2, as in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0b1000_0010&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;scala-36&quot;&gt;&lt;a href=&quot;/news/3.6.2/&quot;&gt;Scala 3.6&lt;/a&gt;&lt;/h3&gt;

&lt;h4 id=&quot;new-stable-features-1&quot;&gt;New stable features&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/clause-interleaving.html&quot;&gt;SIP-47 Clause Interleaving&lt;/a&gt; - type and term parameter clauses can be interleaved, which helps path-dependent APIs.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/match-types-spec.html&quot;&gt;SIP-56 Match Types Specification&lt;/a&gt; - match type extractors follow aliases and singleton types.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/sips/typeclasses-syntax.html&quot;&gt;SIP-64 Improve Syntax for Context Bounds and Givens&lt;/a&gt; - the new context-bound and given syntax, including abstract context bounds on type members.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;breaking-changes-1&quot;&gt;Breaking changes&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Context bounds desugar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt; parameters instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicit&lt;/code&gt; ones. This can shift implicit resolution, and it affects macros or compiler plugins that inspect argument lists by flag.&lt;/li&gt;
  &lt;li&gt;Java-defined annotations with more than one parameter require named arguments. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.6-migration -rewrite&lt;/code&gt; inserts the names on a best-effort basis.&lt;/li&gt;
  &lt;li&gt;Code whose meaning differs under the upcoming given prioritization began to warn, while still compiling under the old rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;scala-37&quot;&gt;&lt;a href=&quot;/news/3.7.0/&quot;&gt;Scala 3.7&lt;/a&gt;&lt;/h3&gt;

&lt;h4 id=&quot;new-stable-features-2&quot;&gt;New stable features&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/binary-api.html&quot;&gt;SIP-52 Binary APIs&lt;/a&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@publicInBinary&lt;/code&gt; keeps inline methods binary compatible without generating unstable accessors.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/named-tuples.html&quot;&gt;SIP-58 Named Tuples&lt;/a&gt; - tuples with named elements, which also allow matching a subset of case-class fields by name and computing structural types without macros.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;breaking-changes-2&quot;&gt;Breaking changes&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Given search now picks the most general matching instance instead of the most specific one. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.5&lt;/code&gt; keeps the old rules and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.7-migration&lt;/code&gt; warns where the two differ; see &lt;a href=&quot;/2024/08/19/given-priority-change-3.7.html&quot;&gt;Upcoming Changes to Givens in Scala 3.7&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Passing an explicit argument to an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicit&lt;/code&gt; parameter warns unless the call site says &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-rewrite -source:3.7-migration&lt;/code&gt; inserts it.&lt;/li&gt;
  &lt;li&gt;The standard library moved to 2.13.16, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.tail&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.init&lt;/code&gt; on the empty string throw instead of returning it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;other-notable-changes-2&quot;&gt;Other notable changes&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;The expression compiler behind Metals and IntelliJ debugging moved into the compiler repository.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Wunused&lt;/code&gt; was rewritten to produce far fewer false positives, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Wconf&lt;/code&gt; gained origin-based filtering.&lt;/li&gt;
  &lt;li&gt;Scala 3 was unblocked on Android by boxing SAM return types the Android runtime rejects.&lt;/li&gt;
  &lt;li&gt;Case classes may have dependent fields, as in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case class ConfigEntry(option: Setting, default: option.Value)&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The REPL can pull in dependencies at runtime with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:jar&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Experimental &lt;a href=&quot;https://docs.scala-lang.org/sips/unroll-default-arguments.html&quot;&gt;SIP-61 Unroll Default Arguments for Binary Compatibility&lt;/a&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@unroll&lt;/code&gt; lets you add default parameters without breaking binary compatibility.&lt;/li&gt;
  &lt;li&gt;Experimental &lt;a href=&quot;https://github.com/scala/improvement-proposals/pull/100&quot;&gt;SIP-68 Referenceable Package Objects&lt;/a&gt; - package objects became referenceable as values.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;scala-38&quot;&gt;&lt;a href=&quot;/news/3.8/&quot;&gt;Scala 3.8&lt;/a&gt;&lt;/h3&gt;

&lt;h4 id=&quot;new-stable-features-3&quot;&gt;New stable features&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/57.html&quot;&gt;SIP-57 Replace non-sensical &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@unchecked&lt;/code&gt; annotations&lt;/a&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtimeChecked&lt;/code&gt; replaces awkward &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;: @unchecked&lt;/code&gt; ascriptions.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/sips/62.html&quot;&gt;SIP-62 For Comprehension Improvements&lt;/a&gt; - Better Fors is now enabled by default, which allows aliases before generators and drops redundant &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;breaking-changes-3&quot;&gt;Breaking changes&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;JDK 17 or newer is required to compile and run.&lt;/li&gt;
  &lt;li&gt;The REPL moved into a separate &lt;a href=&quot;https://index.scala-lang.org/scala/scala3/artifacts/scala3-repl&quot;&gt;scala3-repl&lt;/a&gt; artifact, which embedding tools must depend on explicitly.&lt;/li&gt;
  &lt;li&gt;The standard library is compiled with Scala 3, so its context bounds desugar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;given&lt;/code&gt; and explicit arguments need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt;, as in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array.empty(using ClassTag.Int)&lt;/code&gt;. Running 3.7.4 with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.7-migration -rewrite&lt;/code&gt; fixes most call sites before the bump.&lt;/li&gt;
  &lt;li&gt;This is the boundary where Scala 2.13’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Ytasty-reader&lt;/code&gt; stops consuming Scala 3 artifacts.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-reflect&lt;/code&gt; used by Scala 2.13 dependencies on the classpath may no longer work: initialising &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.reflect.runtime.universe&lt;/code&gt; against the Scala 3 standard library can fail at runtime. Apache Spark is the best-known case. Details are in the &lt;a href=&quot;#runtime-reflection-with-scala-reflect&quot;&gt;migration guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;other-notable-changes-3&quot;&gt;Other notable changes&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;The REPL pretty-prints results with &lt;a href=&quot;https://index.scala-lang.org/com-lihaoyi/fansi&quot;&gt;fansi&lt;/a&gt; and &lt;a href=&quot;https://index.scala-lang.org/com-lihaoyi/pprint&quot;&gt;pprint&lt;/a&gt;, so long values no longer dump as a single unreadable line.&lt;/li&gt;
  &lt;li&gt;The JVM backend gained the Scala 2 bytecode optimizer in 3.8.3. It is opt-in: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-opt&lt;/code&gt; enables local optimizations, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-opt-inline:...&lt;/code&gt; controls inlining across call sites. See the &lt;a href=&quot;/news/3.8.3/&quot;&gt;3.8.3 release notes&lt;/a&gt; and the &lt;a href=&quot;https://docs.scala-lang.org/overviews/compiler-options/optimizer.html&quot;&gt;optimizer documentation&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Lazy vals are implemented with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VarHandle&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sun.misc.Unsafe&lt;/code&gt;, which is how Scala 3.8 can run on JDK 24 and later.&lt;/li&gt;
  &lt;li&gt;Nightly builds moved to &lt;a href=&quot;https://repo.scala-lang.org/&quot;&gt;repo.scala-lang.org&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Experimental &lt;a href=&quot;https://github.com/scala/improvement-proposals/pull/97&quot;&gt;SIP-67 Strict Equality Pattern Matching&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Experimental &lt;a href=&quot;https://github.com/scala/improvement-proposals/pull/105&quot;&gt;SIP-70 Flexible Varargs&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Experimental &lt;a href=&quot;https://github.com/scala/improvement-proposals/pull/118&quot;&gt;SIP-75 Allow single-line lambdas after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Experimental match sub-cases (&lt;a href=&quot;https://github.com/scala/scala3/pull/23786&quot;&gt;#23786&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;migration-guide&quot;&gt;Migration guide&lt;/h2&gt;

&lt;p&gt;For a practical overview of the migration work behind this release, watch &lt;a href=&quot;https://www.youtube.com/watch?v=hhmNxNi0unE&quot;&gt;Migration Without Tears: 2,000 Projects, One New LTS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/VirtusLab/community-build3&quot;&gt;Open Community Build&lt;/a&gt; results shown there are encouraging: &lt;strong&gt;about 1,780 of nearly 2,000 projects&lt;/strong&gt; build on Scala 3.9 with no or minimal changes, mostly thanks to the compiler’s built-in rewrites.&lt;/p&gt;

&lt;h3 id=&quot;recommended-upgrade-order&quot;&gt;Recommended upgrade order&lt;/h3&gt;

&lt;p&gt;A newer compiler should still compile against the libraries you already use. A newer library may require a newer compiler, so do not bump dependencies first.&lt;/p&gt;

&lt;p&gt;Upgrade in this order, and let CI pass and commit after each step:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Upgrade the &lt;strong&gt;build tool&lt;/strong&gt; if required.&lt;/li&gt;
  &lt;li&gt;Move to &lt;strong&gt;JDK&lt;/strong&gt; 17 or later, while staying on the current Scala version where possible.&lt;/li&gt;
  &lt;li&gt;Upgrade &lt;strong&gt;Scala.js&lt;/strong&gt; if the project uses it.&lt;/li&gt;
  &lt;li&gt;Upgrade &lt;strong&gt;Scala&lt;/strong&gt;, including the compiler rewrites below. If you use separate Scala version stepping stones, commit each one.&lt;/li&gt;
  &lt;li&gt;Upgrade &lt;strong&gt;libraries&lt;/strong&gt; after the Scala bump.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For many projects, the migration is just the JDK update and the Scala version bump.
For larger codebases, it is easier to treat the migration as a sequence of small, reviewable compiler-assisted changes than to diagnose every incompatibility after one big jump.&lt;/p&gt;

&lt;h3 id=&quot;compiler-built-in-rewrites&quot;&gt;Compiler built-in rewrites&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Pick a Scala compiler to run the rewrites on:
    &lt;ul&gt;
      &lt;li&gt;Start with &lt;strong&gt;Scala 3.7.4&lt;/strong&gt; if the codebase often passes explicit arguments to standard-library methods that now need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt;. 3.7.4 is the last release before the standard library was compiled with Scala 3, and it can insert those &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt; clauses before the 3.8 library boundary.&lt;/li&gt;
      &lt;li&gt;Start with &lt;strong&gt;Scala 3.9.0&lt;/strong&gt; if the codebase uses a lot of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with&lt;/code&gt; types. 3.9 improved the rewrite of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;; the same flags on 3.7.4 could emit code that does not compile.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;With that compiler, apply the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.x-migration&lt;/code&gt; rewrites in order for each minor you are crossing, always with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-rewrite&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.4-migration&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.5-migration&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.6-migration&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.7-migration&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.8-migration&lt;/code&gt;, then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.9-migration&lt;/code&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;scalacOptions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;-source:3.4-migration&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;-rewrite&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Later flags do not replay earlier patches, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.6-migration&lt;/code&gt; does not apply the 3.4 rewrites. Run each flag in order.&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;Flag&lt;/th&gt;
          &lt;th&gt;What &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-rewrite&lt;/code&gt; changes&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.4-migration&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;• &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt; in types&lt;br /&gt;• &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt; type wildcards to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt;&lt;br /&gt;• &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xs: _*&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xs*&lt;/code&gt;&lt;br /&gt;• &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var x = _&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.compiletime.uninitialized&lt;/code&gt;&lt;br /&gt;• drop &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[this]&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;private[this]&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;protected[this]&lt;/code&gt;&lt;br /&gt;• drop a trailing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt; used only for eta-expansion&lt;br /&gt;• backtick alphanumeric infix operators that are not declared &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;infix&lt;/code&gt;&lt;br /&gt;• insert &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt; on explicit arguments to context-bound parameters&lt;br /&gt;• insert &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case&lt;/code&gt; on refutable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for&lt;/code&gt; generators&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.5-migration&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;• no new rewrites&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.6-migration&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;• named arguments on Java-defined annotations&lt;br /&gt;• &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(x = e)&lt;/code&gt; rewritten to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{x = e}&lt;/code&gt; where it would now be a one-element named tuple instead of an assignment&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.7-migration&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;• insert &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt; at call sites of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicit&lt;/code&gt; parameters&lt;br /&gt;• drop empty &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; that existed only to pass implicits&lt;br /&gt;• rewrite infix named-argument lists such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x op (a = 1, b = 2)&lt;/code&gt; to dotted &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.op(...)&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.8-migration&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;• refutable pattern bindings such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val hd :: tl = xs&lt;/code&gt; gain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.runtimeChecked&lt;/code&gt;&lt;br /&gt;• &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;: @unchecked&lt;/code&gt; ascriptions are rewritten to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.runtimeChecked&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.9-migration&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;• backtick identifiers that contain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;Some changes have no automatic rewrite. Fix those by hand as the compiler reports them.&lt;/li&gt;
  &lt;li&gt;Review each generated diff as ordinary source, then bump to Scala 3.9.0, drop the temporary migration flags, and run the full test suite.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If a change is hard to apply, for example when using illegal match types after &lt;a href=&quot;https://docs.scala-lang.org/sips/match-types-spec.html&quot;&gt;SIP-56&lt;/a&gt;, you can compile that code with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.x&lt;/code&gt; so Scala 3.9 treats the sources as if they were compiled with that earlier version:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;scalacOptions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;-source:3.3&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use this only for a subproject that is otherwise hard to migrate: newer language features stay unavailable until you remove the flag. The older language source rules are respected on a best-effort basis, it should be used as a temporary solution.&lt;/p&gt;

&lt;h3 id=&quot;scala-213-consumers-via-tasty-reader&quot;&gt;Scala 2.13 consumers via TASTy Reader&lt;/h3&gt;

&lt;p&gt;Scala 3 projects can continue consuming Scala 2.13 artifacts.
The reverse direction has a boundary: Scala 2.13’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Ytasty-reader&lt;/code&gt; can consume Scala 3 artifacts up to Scala 3.7, but not Scala 3.8 or later.&lt;/p&gt;

&lt;p&gt;If you publish Scala 3 libraries for users who still consume them from Scala 2.13, read &lt;a href=&quot;/blog/state-of-tasty-reader.html&quot;&gt;State of the TASTy reader and Scala 2.13 ↔ Scala 3 compatibility&lt;/a&gt; before moving those artifacts to Scala 3.9.&lt;/p&gt;

&lt;h3 id=&quot;runtime-reflection-with-scala-reflect&quot;&gt;Runtime reflection with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-reflect&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Scala 3.8 and later can still depend on Scala 2.13 libraries, but there can be issues if a dependency uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-reflect&lt;/code&gt; for runtime reflection.
Runtime reflection in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-reflect&lt;/code&gt; 2.13 depends on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ScalaSignature&lt;/code&gt; attributes in class files. From Scala 3.8 the standard library is compiled with Scala 3 and no longer emits those attributes, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.reflect.runtime.universe&lt;/code&gt; can fail as soon as it initialises; see &lt;a href=&quot;https://github.com/scala/scala3/issues/25896&quot;&gt;scala/scala3#25896&lt;/a&gt; for details.&lt;/p&gt;

&lt;p&gt;There is no planned compiler or standard-library fix, and it is not yet clear whether a workaround in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-reflect&lt;/code&gt; itself is possible. An experimental reimplementation of part of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-reflect&lt;/code&gt; has been tried, but that work is not something you can depend on.&lt;/p&gt;

&lt;p&gt;What you can do today:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Stay on Scala 3.7.x&lt;/strong&gt; if you need those 2.13 artifacts as they are.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Avoid code paths&lt;/strong&gt; that initialise &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.reflect.runtime.universe&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Migrate the reflection&lt;/strong&gt; to the Java reflection API.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h2&gt;

&lt;p&gt;Scala 3.3.9 is expected within the next month and will continue the maintenance of the previous LTS line.
It will backport fixes introduced between Scala 3.8.4 and Scala 3.9.0 that are safe for the 3.3 compatibility guarantees.
Scala 3.3 LTS remains actively maintained for &lt;strong&gt;one year&lt;/strong&gt; after Scala 3.9.0, giving library maintainers time to plan and communicate their move to the new baseline.
Scala 3.9 LTS itself is guaranteed to be maintained for &lt;strong&gt;at least three years&lt;/strong&gt;, the same commitment as for Scala 3.3 LTS; see the &lt;a href=&quot;/blog/2022/08/17/long-term-compatibility-plans.html&quot;&gt;Scala LTS and Scala Next model&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As I write this, Scala 3.10.0-RC1 is already available and will be announced on channels such as &lt;a href=&quot;https://contributors.scala-lang.org/&quot;&gt;contributors.scala-lang.org&lt;/a&gt;.
Scala 3.10 continues the Scala Next line and is expected to contain more breaking changes than 3.9, especially in the standard library.&lt;/p&gt;

&lt;p&gt;A glimpse of what is coming:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The standard library&lt;/strong&gt; continues to move onto Scala 3 constructs, especially by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inline&lt;/code&gt; and replacing implicit classes with extension methods.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/scala/scala3/pull/25731&quot;&gt;Stronger constant folding during inlining&lt;/a&gt;&lt;/strong&gt; fixes several inlining bugs, but also exposes macros that build ill-typed trees - ZIO and a few other macro-heavy libraries needed new releases to stay compatible with it. It was left out of 3.9.0 so the new LTS stays usable with libraries published today, and can still land in a 3.9.x patch if users ask for it.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Features entering preview:&lt;/strong&gt; &lt;a href=&quot;https://docs.scala-lang.org/sips/unroll-default-arguments.html&quot;&gt;SIP-61 Unroll&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/improvement-proposals/pull/118&quot;&gt;SIP-75 relaxed lambda syntax&lt;/a&gt;, and &lt;a href=&quot;https://github.com/scala/improvement-proposals/pull/100&quot;&gt;SIP-68 referenceable package objects&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Experimental&lt;/strong&gt; &lt;a href=&quot;https://github.com/scala/scala3/pull/26156&quot;&gt;inline and specialized traits&lt;/a&gt;, bringing specialization to Scala 3.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/scala/scala3/pull/26497&quot;&gt;Pattern matching on Java records&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Support for select &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt; directives within the REPL, including &lt;a href=&quot;https://github.com/scala/scala3/pull/26507&quot;&gt;dep&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/26788&quot;&gt;toolkit&lt;/a&gt; and &lt;a href=&quot;https://github.com/scala/scala3/pull/26726&quot;&gt;jar&lt;/a&gt;, with more to come.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;The full changelog for Scala 3.9.0 can be as always found in &lt;a href=&quot;https://github.com/scala/scala3/releases/tag/3.9.0&quot;&gt;release note on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Fixing a remote execution vulnerability in sbt</title>
    <link href="https://www.scala-lang.org/blog/2026/08/10/sbt-remote-tcp-advisory.html"/>
    <updated>2026-08-10T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/blog/2026/08/10/sbt-remote-tcp-advisory</id>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post covers work done under the &lt;a href=&quot;https://www.scala-lang.org/blog/2026/01/27/sta-invests-in-scala.html&quot;&gt;Sovereign Tech Fund investment&lt;/a&gt; umbrella: &lt;a href=&quot;https://contributors.scala-lang.org/t/sbt-2-production-ready-roadmap/7351&quot;&gt;sbt 2 Stable Release and Maintenance&lt;/a&gt;. The work is coordinated by the &lt;a href=&quot;https://scala.epfl.ch/&quot;&gt;Scala Center&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;

&lt;p&gt;Only builds that explicitly set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;serverConnectionType&lt;/code&gt; are affected. You can remove the setting from your build, or upgrade to sbt 1.12.15 / sbt 2.0.6 or later by putting the following in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project/build.properties&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;sbt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.12&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that installing a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt&lt;/code&gt; command does not affect the sbt version used by each individual build.&lt;/p&gt;

&lt;h2 id=&quot;the-vulnerability&quot;&gt;The vulnerability&lt;/h2&gt;

&lt;p&gt;As part of our ongoing work on the sbt 2 release, we’ve been reviewing bug reports and pull requests.&lt;/p&gt;

&lt;p&gt;Recently we received a security report &lt;a href=&quot;https://github.com/sbt/sbt/security/advisories/GHSA-m2pw-22cj-jq4v&quot;&gt;GHSA-m2pw-22cj-jq4v&lt;/a&gt; from &lt;a href=&quot;https://github.com/arpitjain099&quot;&gt;Arpit Jain&lt;/a&gt; that an attacker is able to execute arbitrary code remotely via the sbt server when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;serverConnectionType&lt;/code&gt; is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConnectionType.Tcp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By default, sbt uses UNIX domain sockets on Linux and macOS, and named pipes on Windows, but this can be changed to TCP using the following setting:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Global&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;serverConnectionType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ConnectionType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;Tcp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will use a TCP port that can be calculated deterministically from the working directory, e.g. 5001, for the sbt server communication. An attacker can then craft a JSON-RPC message, masquerading as an sbt client.&lt;/p&gt;

&lt;p&gt;In a normal sequence, using TCP would go through a token authentication so only the local user can use the sbt server; however, there were several endpoints that were not protected by the access control, which allowed improper escalation. This is a form of &lt;a href=&quot;https://cwe.mitre.org/data/definitions/425.html&quot;&gt;CWE-425: Direct Request&lt;/a&gt;. The vulnerability has existed since sbt 1.1.0 and affects both the sbt 1.x and sbt 2.x series.&lt;/p&gt;

&lt;h2 id=&quot;the-fix&quot;&gt;The fix&lt;/h2&gt;

&lt;p&gt;The primary fix was to make sure all LSP-like endpoints are protected behind authorization when using TCP. The fix is available in sbt 1.12.15 and 2.0.6. The remediation was implemented by Eugene and Anatolii using GitHub’s private fork feature. The full advisory is available as &lt;a href=&quot;https://github.com/sbt/sbt/security/advisories/GHSA-m2pw-22cj-jq4v&quot;&gt;GHSA-m2pw-22cj-jq4v&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We recommend removing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;serverConnectionType&lt;/code&gt; setting from your build, or upgrading to a patched version sbt 1.12.15 / sbt 2.0.6 or later.&lt;/p&gt;

&lt;h2 id=&quot;ai-tooling&quot;&gt;AI tooling&lt;/h2&gt;

&lt;p&gt;When Claude Mythos 5 was announced, it was widely reported that the LLM had reached the ability to discover new vulnerabilities in software. Subsequent availability of Claude Fable 5 and competing models have put the idea to the test. In the security report, the reporter has noted that he used AI assistance for the code audit and for drafting this report, and including detailed tracing of functions across multiple source files. When we prompted Claude Fable 5 to discover vulnerabilities, it downgraded itself to a previous model as a safeguard, but discovered the same remote execution bug nonetheless. We might actually be in the age of discovery-capable LLMs.&lt;/p&gt;

&lt;p&gt;We’re thankful that the vulnerability was reported to the sbt team. If you find one please report through &lt;a href=&quot;https://github.com/sbt/sbt/security/advisories&quot;&gt;GitHub advisories&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;participation&quot;&gt;Participation&lt;/h2&gt;

&lt;p&gt;The Scala Center has been entrusted with coordinating the commissioned Scala work for the Sovereign Tech Fund. The Scala Center is an independent, not-for-profit center sponsored by &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;corporate members and individual backers like you&lt;/a&gt; to promote and facilitate Scala. If you would like to participate and/or see more of these types of efforts, please reach out to your manager to see if your company can donate engineering time or membership to the Scala Center.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;The Scala Center Fundraising Campaign&lt;/a&gt; for more details.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Coaxing quality output from generative AI</title>
    <link href="https://www.scala-lang.org/blog/2026/07/06/quality-from-genai.html"/>
    <updated>2026-07-06T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/blog/2026/07/06/quality-from-genai</id>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post covers work done under the &lt;a href=&quot;https://www.scala-lang.org/blog/2026/01/27/sta-invests-in-scala.html&quot;&gt;Sovereign Tech Fund investment&lt;/a&gt;. The work is coordinated by the &lt;a href=&quot;https://scala.epfl.ch/&quot;&gt;Scala Center&lt;/a&gt;. The work described in this post was done by Bill Venners and Chua Chee Seng of &lt;a href=&quot;https://www.artima.com&quot;&gt;Artima&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the tasks funded under the STA project is to improve Scala’s API documentation. Such a task looks like a natural fit for generative AI, because the work is repetitive and the code to document is nearby in the source. But handing the work to an AI raises two challenges. The first is quality: an AI model will readily produce documentation, but it may be mediocre or wrong. The second challenge is managing human review time: someone will have to check all that output. This post is a report on how we approached these problems when using AI to improve API documention of Scala’s standard library: what we tried and how it worked out.&lt;/p&gt;

&lt;p&gt;Quality writing requires iteration. You write a draft, review it (or have someone else review it), then improve it. You repeat this process until you’re happy with the quality. One way to achieve quality with generative AI, therefore, is to delegate the writing part to the AI model and review it yourself, but this doesn’t scale. An AI model can generate content at a much greater rate than you can review it. Because of this, we decided to use the &lt;a href=&quot;https://en.wikipedia.org/wiki/LLM-as-a-Judge&quot;&gt;“LLM as a judge”&lt;/a&gt; technique in an attempt to raise the quality of the output as high as possible prior to asking humans to review it.&lt;/p&gt;

&lt;p&gt;Another way we tried to raise the quality of the AI output prior to human review is to use &lt;em&gt;harnesses&lt;/em&gt; to orchestrate the AI work. First, we wrote a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;todo-writer&lt;/code&gt; application that reformatted doc comments for consistency and inserted text markers in the standard library source to precisely indicate where we wanted an AI to insert focused documentation. Then we created a script to drive the filling-in process. Finally, we attempted to keep the review tasks for humans to a reasonable size.&lt;/p&gt;

&lt;p&gt;The rest of this post describes five techniques that formed our overall approach.&lt;/p&gt;

&lt;h2 id=&quot;technique-1-push-work-onto-deterministic-code&quot;&gt;Technique 1: Push work onto deterministic code&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/scala/scala3/pull/24754&quot;&gt;first pull request&lt;/a&gt; we submitted, which made the style of existing documentation more consistent, was done simply by asking an AI model to find and make the changes, and then reviewing the results. This prompting technique worked fine given the limited scope of those changes.&lt;/p&gt;

&lt;p&gt;Next, we wrote and ran a Scala application to convert wikidoc to markdown, the recommended markup language for Scala 3, and ran it across the entire standard library. We hoped this would make the documentation in the source code nicer for humans to work with. We also felt it would provide a more consistent canvas on which into ask AI models to fill in missing documentation. This resulted in our &lt;a href=&quot;https://github.com/scala/scala3/pull/25113&quot;&gt;second pull request&lt;/a&gt;. The application we used was &lt;a href=&quot;https://github.com/artimahub/scala3/tree/feature-todo-writer/todo-writer&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;todo-writer&lt;/code&gt;&lt;/a&gt;, run with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--migrate-markdown&lt;/code&gt; command line argument.&lt;/p&gt;

&lt;p&gt;We next ran &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;todo-writer&lt;/code&gt; across the standard library to insert &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TODO FILL IN&lt;/code&gt; markers wherever existing documentation was missing any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@param&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@tparam&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@return&lt;/code&gt; tags. Here’s an example:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/** Creates a new map obtained by updating this map with a given key/value pair.
 *  @tparam V1 TODO FILL IN
 *  @param key TODO FILL IN
 *  @param value TODO FILL IN
 *  @return TODO FILL IN
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;updated&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;V1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;V1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;K&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;V1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TODO FILL IN&lt;/code&gt; is one precise marker, which turned the AIs’ job from the open-ended “find and improve the documentation” into the mechanical “replace this text with the right content.” We could now focus the models on exactly those spots, with nothing about where to write or what needed writing left to their judgment.&lt;/p&gt;

&lt;p&gt;The principle underneath this technique is to use determinism wherever you can. Lean on a deterministic program for every part of the job that does not genuinely require judgment, and strip out any nondeterminism that is not essential. &lt;em&gt;Every piece of the job you hand to deterministic code is a piece the AI cannot get wrong.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;technique-2-enforce-a-deterministic-process&quot;&gt;Technique 2: Enforce a deterministic process&lt;/h2&gt;

&lt;p&gt;Another way we used determinism was by defining and enforcing a &lt;em&gt;process&lt;/em&gt; through a shell script that called into the AI model, rather than asking an AI to run the entire task. This kind of orchestration is often called an “AI harness,” which both implies that an AI workhorse is being constrained as well as being put to productive use.&lt;/p&gt;

&lt;p&gt;Our harness used two git branches. Once &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;todo-writer&lt;/code&gt; had inserted the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TODO FILL IN&lt;/code&gt; markers, we committed its output one file at a time, so that every file landed in its own commit, each carrying the same message: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Todo-writer added TODOs for @param, @tparam, and @return tags.&lt;/code&gt; A small helper, &lt;a href=&quot;https://github.com/artimahub/scala3/blob/b8eb945dd37192706a88fa645475b7fd97182b0f/todo-writer/commit-each-file.sh&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commit-each-file.sh&lt;/code&gt;&lt;/a&gt;, did this slicing. The effect was to turn the whole task into an ordered queue of single-file commits on a &lt;em&gt;source&lt;/em&gt; branch, with nothing else mixed in.&lt;/p&gt;

&lt;p&gt;The loop itself, &lt;a href=&quot;https://github.com/artimahub/scala3/blob/384855e9c3e900796590a7ed44a4bdcc133b9a0d/todo-writer/fill-todos-loop.sh&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fill-todos-loop.sh&lt;/code&gt;&lt;/a&gt;, drained that queue onto a separate working branch. It listed the source commits not yet present on the working branch, oldest first, and handled them one at a time. For each commit it did five things. It cherry-picked the single-file change onto the working branch, so the file arrived with its TODO markers as one isolated commit. It ran a writer model (&lt;a href=&quot;https://github.com/artimahub/scala3/blob/384855e9c3e900796590a7ed44a4bdcc133b9a0d/todo-writer/prompts/writer-prompt.txt&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;writer-prompt.txt&lt;/code&gt;&lt;/a&gt;) that replaced the TODOs in that one file with real documentation. It ran a reviewer model (&lt;a href=&quot;https://github.com/artimahub/scala3/blob/384855e9c3e900796590a7ed44a4bdcc133b9a0d/todo-writer/prompts/reviewer-prompt.txt&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reviewer-prompt.txt&lt;/code&gt;&lt;/a&gt;) that inspected the result and returned a structured JSON verdict. It ran the writer once more (&lt;a href=&quot;https://github.com/artimahub/scala3/blob/384855e9c3e900796590a7ed44a4bdcc133b9a0d/todo-writer/prompts/refinement-prompt.txt&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;refinement-prompt.txt&lt;/code&gt;&lt;/a&gt;) to act on that verdict. And finally it amended the cherry-picked commit, so that the file’s single commit now held finished documentation instead of placeholders.&lt;/p&gt;

&lt;p&gt;The cherry-picking played a critical role: it was the loop’s iterator. Each source commit was exactly one unit of work, so cherry-picking popped the next file off the queue in order. The AI model never had to decide for itself which files needed attention or in what sequence, because that was settled when the queue was built. It also guaranteed that the output kept the same clean shape as the input, one commit per file, which later let us regroup the finished commits into review-sized pull requests. And because a file that had already been processed no longer appeared in the not-yet-applied range, the run was naturally restartable and could proceed in batches.&lt;/p&gt;

&lt;p&gt;The benefit of this harness was to keep the AIs focused on small, isolated tasks inside a fixed process of create, review, and refine. That process takes time, but not my time: I ran it overnight while I slept, with deliberate pauses between files to spread out my token usage. (Note that if you need a task to finish faster in wall-clock terms, you can design processes that run in parallel.)&lt;/p&gt;

&lt;h2 id=&quot;technique-3-give-the-ai-a-fresh-focused-context&quot;&gt;Technique 3: Give the AI a fresh, focused context&lt;/h2&gt;

&lt;p&gt;Our script gave the AI a fresh context for every step, not just for every file. For a single file the writer filled the TODOs in a fresh context, the reviewer judged the result in a second fresh context, and the refiner applied the review in a third, with nothing carried between them except the file itself and the reviewer’s written feedback. I kept each of those contexts as small as possible for two reasons: as context length increases, output quality can decline, and a larger context consumes more tokens on every turn. Although I was on a monthly subscription, I still did not want to burn more tokens than necessary.&lt;/p&gt;

&lt;p&gt;That is also what gave the review step its independence. Because the reviewer started fresh, it never saw the reasoning the writer had used, so it came to the documentation cold even though it was the exact same AI model. Another approach is to use a different model for review, to reduce the chance that the reviewer shares the writer’s blind spots.&lt;/p&gt;

&lt;h2 id=&quot;technique-4-separate-the-review-from-the-decision&quot;&gt;Technique 4: Separate the review from the decision&lt;/h2&gt;

&lt;p&gt;I used the same AI model for every step, and though it may have been a better choice to use a different model for review, the results showed that one model is sufficient, so long as each step runs in its own fresh context and is handed a single, clearly defined role. Across the loop that same model played three tightly focused roles, never more than one at a time:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;The writer&lt;/strong&gt; received a file full of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TODO FILL IN&lt;/code&gt; markers and a single instruction: replace them with real documentation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;The reviewer&lt;/strong&gt; examined the writer’s output and offered suggestions, emitting its findings as structured JSON. The reviewer’s only job was to critique and suggest; it changed nothing and decided nothing.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;The refiner&lt;/strong&gt; read the reviewer’s JSON alongside the file and made the call, deciding which suggestions to accept and which to ignore, and editing the documentation accordingly.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Separating these roles is the whole point. The reviewer never was given the opportunity to act on its own opinions; a separate session weighed those opinions against the file and decided what to do. And although a single model sat behind all three roles, each came to its task cold, with no memory of having written or judged the very thing in front of it. The model stayed the same; the role, and the context, were different every time.&lt;/p&gt;

&lt;h2 id=&quot;technique-5-size-the-pull-requests-to-the-human&quot;&gt;Technique 5: Size the pull requests to the human&lt;/h2&gt;

&lt;p&gt;When it was time for human review, we packaged the changes into multiple PRs to make it more manageable. Although it was far better than one massive pull request containing all changes, the PRs we submitted still stretched what can be reasonably reviewed by humans.&lt;/p&gt;

&lt;p&gt;The first pass shipped as twelve pull requests, split by area of the library: &lt;a href=&quot;https://github.com/scala/scala3/pull/25371&quot;&gt;#25371&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/25372&quot;&gt;#25372&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/25373&quot;&gt;#25373&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/25374&quot;&gt;#25374&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/25375&quot;&gt;#25375&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/25376&quot;&gt;#25376&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/25377&quot;&gt;#25377&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/25378&quot;&gt;#25378&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/25379&quot;&gt;#25379&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/25380&quot;&gt;#25380&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/25381&quot;&gt;#25381&lt;/a&gt;, and &lt;a href=&quot;https://github.com/scala/scala3/pull/25996&quot;&gt;#25996&lt;/a&gt;. Not all of them were comfortably human-sized; some were large enough that reviewing them in a single sitting was a slog. The humans slogged through anyway, and the work needed it: reviewers caught real problems in the generated documentation - inconsistencies across files, edits to text that should have been left untouched, broken Scaladoc markup, and some outright factual mistakes - and we fixed those within the same pull requests before they were merged.&lt;/p&gt;

&lt;p&gt;A second round of pull requests followed, for a different reason. During the initial review, we found and fixed bugs in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;todo-writer&lt;/code&gt; itself: the earlier version had skipped some declarations that should have received tags, such as higher-kinded type parameters and multi-parameter-list constructors. Once those bugs were fixed, we re-ran the improved tool across the library, which surfaced the spots the original pass had missed. The newly added tags went into nine cleanup pull requests: &lt;a href=&quot;https://github.com/scala/scala3/pull/26119&quot;&gt;#26119&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/26120&quot;&gt;#26120&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/26121&quot;&gt;#26121&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/26122&quot;&gt;#26122&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/26123&quot;&gt;#26123&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/26124&quot;&gt;#26124&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/26125&quot;&gt;#26125&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala/scala3/pull/26126&quot;&gt;#26126&lt;/a&gt;, and &lt;a href=&quot;https://github.com/scala/scala3/pull/26127&quot;&gt;#26127&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;

&lt;p&gt;Everything described here filled in tags on declarations that already had a Scaladoc comment. The larger job still ahead is to document the declarations that have none at all, and there are many: 5,894 program entities in the standard library currently have no Scaladoc comment whatsoever. That is a harder problem than supplying a missing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@param&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@return&lt;/code&gt;, because there is no existing summary to build on, so reaching high quality will take more than the single create, review, and refine pass we relied on here.&lt;/p&gt;

&lt;p&gt;For that next batch I want to elaborate the review side of the loop. Instead of a single reviewer, I plan to run several reviews of each change, including reviews by different AI models, so that more eyes, and more kinds of eyes, weigh in before any human does. The aim is the same as before: push the quality as high as the machines can take it, so that by the time a human takes over, the documentation is already good.&lt;/p&gt;

&lt;h2 id=&quot;about-the-author&quot;&gt;About the author&lt;/h2&gt;

&lt;p&gt;Bill Venners is president of &lt;a href=&quot;https://www.artima.com&quot;&gt;Artima, Inc.&lt;/a&gt; He is the lead developer of the ScalaTest and Scalactic open source libraries and coauthor of &lt;a href=&quot;https://www.artima.com/shop/programming_in_scala_5ed&quot;&gt;Programming in Scala, Fifth Edition&lt;/a&gt; and &lt;a href=&quot;https://www.artima.com/shop/advanced_programming_in_scala_5ed&quot;&gt;Advanced Programming in Scala, Fifth Edition&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;about-the-scala-center&quot;&gt;About the Scala Center&lt;/h2&gt;

&lt;p&gt;The Scala Center has been entrusted with coordinating the commissioned Scala work for the Sovereign Tech Fund. The Scala Center is an independent, not-for-profit center sponsored by &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;corporate members and individual backers like you&lt;/a&gt; to promote and facilitate Scala. If you would like to participate and/or see more of these types of efforts, please reach out to your manager to see if your company can donate engineering time or membership to the Scala Center.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;The Scala Center Fundraising Campaign&lt;/a&gt; for more details.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>sbt 2 is now available!</title>
    <link href="https://www.scala-lang.org/blog/2026/06/29/sbt2.html"/>
    <updated>2026-06-29T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/blog/2026/06/29/sbt2</id>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post covers work done under the &lt;a href=&quot;https://www.scala-lang.org/blog/2026/01/27/sta-invests-in-scala.html&quot;&gt;Sovereign Tech Fund investment&lt;/a&gt; umbrella: &lt;a href=&quot;https://contributors.scala-lang.org/t/sbt-2-production-ready-roadmap/7351&quot;&gt;sbt 2 Stable Release and Maintenance&lt;/a&gt;. The work is coordinated by the &lt;a href=&quot;https://scala.epfl.ch/&quot;&gt;Scala Center&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After five years of development, sbt 2 is out. Since the experimental sudori part 1 blog post in 2021, more than 82 people have contributed to the project. We would like to thank community and corporate contributors, Scala Center, and Sovereign Tech Fund for their support.&lt;/p&gt;

&lt;h2 id=&quot;whats-new-in-sbt-2&quot;&gt;What’s new in sbt 2?&lt;/h2&gt;

&lt;p&gt;sbt 2 is a new version of sbt. If you’re familiar with sbt 1.x, hopefully the jump is not too far, but we have pushed sbt to the modern standard. The headline features are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;sbt 2.x uses Scala 3.8.4 for build definitions and plugins (Both sbt 1.x and 2.x are capable of building Scala 2.x and 3.x), which requires minimum &lt;strong&gt;JDK 17&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Uses sbtn (native-image client) for faster startup.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; changed to incremental test.&lt;/li&gt;
  &lt;li&gt;Local/remote cache system that is Bazel-compatible. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compile&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; are both rewritten to be cachable tasks.&lt;/li&gt;
  &lt;li&gt;Project matrix, which was available via plugin in sbt 1.x, is in-sourced in sbt 2.x.&lt;/li&gt;
  &lt;li&gt;Client-side run.&lt;/li&gt;
  &lt;li&gt;Client-side console.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.scala-sbt.org/2.x/docs/en/&quot;&gt;New documentation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;
For more details, please check out &lt;a href=&quot;https://www.scala-sbt.org/2.x/docs/en/changes/sbt-2.0-change-summary.html&quot;&gt;sbt 2.0 changes summary&lt;/a&gt; and the Scala Days 2025 talk &lt;a href=&quot;https://www.youtube.com/watch?v=GM2ywMb4z7A&quot;&gt;sbt 2.0: go big&lt;/a&gt; from 2025.&lt;/p&gt;

&lt;h2 id=&quot;how-do-i-get-started-with-sbt-2&quot;&gt;How do I get started with sbt 2?&lt;/h2&gt;

&lt;p&gt;The sbt version used for your build is upgraded by putting the following in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project/build.properties&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sbt.version&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This mechanism allows that sbt 2.0.1 is used only for the builds that you want.&lt;/p&gt;

&lt;p&gt;Download &lt;strong&gt;the official sbt runner&lt;/strong&gt; from SDKMAN, or download from &lt;a href=&quot;https://github.com/sbt/sbt/releases/tag/v2.0.1&quot;&gt;https://github.com/sbt/sbt/releases/tag/v2.0.1&lt;/a&gt; to upgrade the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt&lt;/code&gt; shell script, sbtn, and the launcher.&lt;/p&gt;

&lt;h2 id=&quot;repopulating-the-plugin-ecosystem&quot;&gt;Repopulating the plugin ecosystem&lt;/h2&gt;

&lt;p&gt;Major plugins are already available on sbt 2.x.&lt;/p&gt;

&lt;p&gt;Under the sbt 2 workstream, Anatolii from Scala Center has created &lt;a href=&quot;/blog/2026/03/02/sbt2-compat.html&quot;&gt;the sbt2-compat plugin&lt;/a&gt;, which bridges the source-level differences between sbt 1.x and 2.x. This allows cross-building of a plugin, aiding the migration process. Also under the STA workstream, Rikito Taniguchi from VirtusLab has &lt;a href=&quot;https://github.com/scala-js/scala-js/pull/5314&quot;&gt;cross built Scala.JS plugin to sbt 2.x (scala-js#5314)&lt;/a&gt;.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Plugin&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Version&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Published&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Scala.JS&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.22.0&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Scala Native&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.5.11&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;sbt-assembly&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.3.1&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Play&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3.1.0-M9&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;⚠️&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;This means we can now cross build JVM / JS / Native using sbt 2.x!&lt;/p&gt;

&lt;h2 id=&quot;client-server-by-default&quot;&gt;Client-server by default&lt;/h2&gt;

&lt;p&gt;The sbt runner script is capable of running either sbt 1.x build or 2.x build. When the sbt runner detects an sbt 2.x build, it will now launch the native sbtn client. This will start the sbt server as a background process, and sbtn will send the command. This means that, if you wish, you can use your system shell:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sbt compile
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sbt &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The client program is gradually getting richer. For example, it can launch Scala REPL when the console task is detected. This keeps sbt server available for other tasks.&lt;/p&gt;

&lt;h2 id=&quot;project-matrix&quot;&gt;Project matrix&lt;/h2&gt;

&lt;p&gt;sbt 2.x ships with project matrix, which lets you cross build multiple versions of Scala and multiple platforms (JVM, JS, and Native). With projectMatrix, you declare the platform rows you want in one place. Each row becomes a normal subproject. For example, this defines JVM, Scala.js, and Scala Native rows:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;core&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projectMatrix&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;core&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;core&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;jvmPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(...)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;nativePlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(...)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;jsPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For Scala.js and Scala Native, add the plugins:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// project/plugins.sbt&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;addSbtPlugin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;org.scala-native&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sbt-scala-native&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0.5.11&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;addSbtPlugin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;org.scala-js&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sbt-scalajs&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.22.0&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;using-cross-published-libraries&quot;&gt;Using cross-published libraries&lt;/h2&gt;

&lt;p&gt;In sbt 1.x, Scala.js and Scala Native builds required &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%%%&lt;/code&gt; for dependencies, so that the platform-specific suffix is included in the artifact name. In sbt 2.x, cross-built dependencies can be written with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%%&lt;/code&gt;, just like JVM libraries:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;libraryDependencies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;org.typelevel&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;cats-effect&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;3.5.4&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See &lt;a href=&quot;https://www.scala-sbt.org/2.x/docs/en/concepts/cross-building.html&quot;&gt;Cross building&lt;/a&gt; and &lt;a href=&quot;https://www.scala-sbt.org/2.x/docs/en/reference/cross-building-setup.html&quot;&gt;Cross building setup&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h2 id=&quot;let-us-know-what-you-think&quot;&gt;Let us know what you think&lt;/h2&gt;

&lt;p&gt;Have you tried sbt 2? Let us know what you think in &lt;a href=&quot;https://github.com/sbt/sbt/discussions/9338&quot;&gt;the discussion forum&lt;/a&gt;. If you find a bug, &lt;a href=&quot;https://github.com/sbt/sbt/issues&quot;&gt;please let us know&lt;/a&gt; as well.&lt;/p&gt;

&lt;h2 id=&quot;participation&quot;&gt;Participation&lt;/h2&gt;

&lt;p&gt;The Scala Center has been entrusted with coordinating the commissioned Scala work for the Sovereign Tech Fund. The Scala Center is an independent, not-for-profit center sponsored by &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;corporate members and individual backers like you&lt;/a&gt; to promote and facilitate Scala. If you would like to participate and/or see more of these types of efforts, please reach out to your manager to see if your company can donate engineering time or membership to the Scala Center.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;The Scala Center Fundraising Campaign&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;sbt 2 was brought to you by many contributors, including those who contributed to sbt 1.x series, migrating plugins, but according to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git shortlog -sn --no-merges 00eba85d98c854527125ae1655b5332c19b5afd8...733bcfb23997930915b563e7d27b1a1f6c0490da --not 1.11.x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git shortlog -sn --group=author --group=trailer:co-authored-by --no-merges 242bd18d30c418620024d089b587f6d263d34247...v2.0.0 --not 1.12.x&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-plain&quot;&gt;545 Eugene Yokota (eed3si9n)
217 Kenji Yoshida (xuwei-k)
146 Adrien Piquerez
51  Jerry Tan (friendseeker)
37  MkDev11
34  bitloi
30  Scala Steward
21  calm329
16  Anatolii Kmetiuk
15  dependabot[bot]
14  Yasuhiro Tatsuno
13  E.G
11  Pandaman
10  João Ferreira
9   Anton Sviridov
9   Brian Hotopp
8   Aleksandra Zdrojowa
7   Dream
7   GlobalStar117
7   Matt Dziuban
5   Dairus
4   Martin Duhem
4   john0030710
3   Angel98518
3   Brice Jaglin
3   Li Haoyi
3   gayanMatch
2   Ali Rashid
2   Billy Autrey
2   BitToby
2   Damian Reeves
2   Daniil Sivak
2   Dmitrii Naumenko
2   Douglas Ma
2   Frank S. Thomas
2   Jame4u
2   Josh Soref
2   Kamil Podsiadło
2   Marco Zühlke
2   Matthew de Detrich
2   Matthias Kurz
2   Michał Pawlik
2   Miguel Vilá
2   NeedmeFordev
2   Pluto
2   Renzo
2   Rikito Taniguchi
2   SID
2   Satoshi Dev
2   byteforge
2   circlecrystalin
2   it-education-md
1   Albert Meltzer
1   Deborah Funmilola Olaboye
1   Eve
1   Francluob
1   Guillaume Massé
1   Hamza Remmal
1   Hugo van Rijswijk
1   Idan Ben-Zvi
1   Jakub Kozłowski
1   James Roper
1   Karl Yngve Lervåg
1   Lazz
1   Lukas Rytz
1   Nikita Vilunov
1   OlegYch
1   Pegasus
1   Rex Kerr
1   Roberto Tyley
1   Saber
1   SalesforcePeak
1   SlowBrainDude
1   Zainab Ali
1   bohdansolovie
1   chrisrock1124
1   corevibe555
1   dev-miro26
1   dive2tech
1   fireXtract
1   kijuky
1   nathanlao
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Thanks to everyone who’s helped improve sbt and Zinc by using them, reporting bugs, improving our documentation, porting builds, porting plugins, and submitting and reviewing pull requests.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Scala 3.3.8 LTS is now available!</title>
    <link href="https://www.scala-lang.org/news/3.3.8/"/>
    <updated>2026-06-10T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/news/release-notes-3.3.8</id>
    <content type="html">&lt;p&gt;Scala 3.3.8 LTS is now available!&lt;/p&gt;

&lt;p&gt;This patch release backports most of the bugfixes and some of the improvements
introduced in the Scala Next series to the Scala 3.8.4 release. All of the
backported changes were proven to not break either binary or source
compatibility, by testing over 1500 projects in the
&lt;a href=&quot;https://github.com/VirtusLab/community-build3&quot;&gt;Scala 3 Open Community Build&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;notable-changes&quot;&gt;Notable changes&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;Support for JDK 26 &lt;a href=&quot;https://github.com/scala/scala3/pull/24430&quot;&gt;#24430&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Multiple coverage improvement to make it on par with Scala 2 support including
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;// $COVERAGE-OFF$&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;// $COVERAGE-ON$&lt;/code&gt; markers&lt;/li&gt;
  &lt;li&gt;New @uncheckedOverride annotation for definitions that may override.
&lt;a href=&quot;https://github.com/scala/scala3/pull/24545&quot;&gt;#24545&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Trap Ctrl-C in the REPL: if no command is running clear the prompt, if some
command is running ask for confirmation before exiting.
&lt;a href=&quot;https://github.com/scala/scala3/pull/24127&quot;&gt;#24127&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Numerous linting and presentation compiler improvements and fixes.&lt;/li&gt;
  &lt;li&gt;New &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Yfuture-lazy-vals&lt;/code&gt; options that allows to compile with new lazy val
implementation compatible with all JDK 9+
&lt;a href=&quot;https://github.com/scala/scala3-lts/pull/637&quot;&gt;#637&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a full list of changes and contributor credits, please refer to the
&lt;a href=&quot;https://github.com/scala/scala3/releases/tag/3.3.8&quot;&gt;release notes&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;scala-lts-release-notice&quot;&gt;Scala LTS Release Notice&lt;/h2&gt;

&lt;p&gt;The next planned LTS 3.3 release will include updates introduced until last
Scala 3.9.x before 3.10. Scala 3.9.x will also be a new LTS release. We’ll
continue to backport bug fixes and improvements from the Scala Next series to
the 3.3.x series for the next year after the release 3.9.0.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Improving Scala's docs and website</title>
    <link href="https://www.scala-lang.org/blog/2026/06/09/sovereign-doc-project.html"/>
    <updated>2026-06-09T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/blog/2026/06/09/sovereign-doc-project</id>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post covers work done under the &lt;a href=&quot;https://www.scala-lang.org/blog/2026/01/27/sta-invests-in-scala.html&quot;&gt;Sovereign Tech Fund investment&lt;/a&gt;. The work is coordinated by the &lt;a href=&quot;https://scala.epfl.ch/&quot;&gt;Scala Center&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We have collected possible documentation tasks from three sources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Tasks in the &lt;strong&gt;original proposal&lt;/strong&gt; we made to the Sovereign Tech Agency&lt;/li&gt;
  &lt;li&gt;Tasks collected in &lt;strong&gt;internal discussions&lt;/strong&gt; since then&lt;/li&gt;
  &lt;li&gt;Tasks from &lt;strong&gt;community suggestions&lt;/strong&gt; on &lt;a href=&quot;https://contributors.scala-lang.org/t/scala-documentation-web-sites-what-should-be-improved/7354&quot;&gt;this Contributors forum thread&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This blog post &lt;strong&gt;summarizes&lt;/strong&gt; what we have collected, &lt;strong&gt;identifies tasks&lt;/strong&gt; that we have chosen to tackle, and &lt;strong&gt;describes work&lt;/strong&gt; that is already underway.&lt;/p&gt;

&lt;h2 id=&quot;project-goals&quot;&gt;Project goals&lt;/h2&gt;

&lt;p&gt;We aim to identify documentation, both API documentation (Scaladoc) and the docs on the Scala website, that is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Outdated, or&lt;/li&gt;
  &lt;li&gt;Incomplete or poor quality, or&lt;/li&gt;
  &lt;li&gt;Missing entirely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And we want to address those shortcomings, to aid both:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;New users coming to Scala&lt;/li&gt;
  &lt;li&gt;Existing users of Scala&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;project-scope&quot;&gt;Project scope&lt;/h2&gt;

&lt;p&gt;A major focus will be on the &lt;strong&gt;Scaladoc for the standard library&lt;/strong&gt;. We will update and expand it. Along the way, if we find that limitations of the Scala 3 Scaladoc tool are causing quality issues in the doc, improving the tool is in scope.&lt;/p&gt;

&lt;p&gt;The project scope also includes the &lt;strong&gt;documentation on our website&lt;/strong&gt; such as the Scala language specification, getting-started docs, language tour, features guides, Scala Toolkit documentation, and so forth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scala 3 is the primary focus&lt;/strong&gt;, but we can also make especially important improvements on the Scala 2 side.&lt;/p&gt;

&lt;h2 id=&quot;whats-not-in-scope&quot;&gt;What’s not in scope?&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Third-party&lt;/strong&gt; tools, libraries, and publications are not in scope.&lt;/p&gt;

&lt;p&gt;That said, it is sometimes appropriate for our website and docs to &lt;strong&gt;describe and link to&lt;/strong&gt; third-party documentation and resources. Examples of such documentation that is in scope for improvement include: the Scala &lt;a href=&quot;https://www.scala-lang.org/community/&quot;&gt;community page&lt;/a&gt;, the Scala &lt;a href=&quot;https://docs.scala-lang.org/getting-started/scala-ides.html&quot;&gt;IDEs page&lt;/a&gt;, the Scala &lt;a href=&quot;https://docs.scala-lang.org/toolkit/introduction.html&quot;&gt;Toolkit documentation&lt;/a&gt; (because the Toolkit includes third-party libraries), and the Scala &lt;a href=&quot;https://docs.scala-lang.org/books.html&quot;&gt;books page&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-did-we-initially-propose&quot;&gt;What did we initially propose?&lt;/h2&gt;

&lt;p&gt;In the Center’s original proposal we identified the following areas or “work packages”.&lt;/p&gt;

&lt;p&gt;Any work we do must fit in at least one of these areas, and we must do some work in all of the areas. Note that the “Website” area is especially broad and can cover a wide variety of documentation tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Work Package F: Documentation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;F.1: Scaladoc: Core classes including collections&lt;/li&gt;
  &lt;li&gt;F.2: Scaladoc: Other classes&lt;/li&gt;
  &lt;li&gt;F.3: Scaladoc: Scala 3-specific classes&lt;/li&gt;
  &lt;li&gt;F.4: Website&lt;/li&gt;
  &lt;li&gt;F.5: Scaladoc: Individual methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;F.1/F.2/F.3 are for class-level documentation, F.5 for the methods within those classes.&lt;/p&gt;

&lt;h2 id=&quot;what-work-is-ongoing&quot;&gt;What work is ongoing?&lt;/h2&gt;

&lt;p&gt;Work on &lt;strong&gt;improving our API documentation&lt;/strong&gt; (Scaladoc) is already well underway. A series of PRs has already been merged and others are in the pipeline. These PRs were created with the help of AI-based tooling developed by Bill Venners and Chua Chee Seng. The process of doing this work with AI assistance will be documented, and the results described, in a future blog post by Bill.&lt;/p&gt;

&lt;p&gt;Thanks to work done by Oliver Bračevac (from the Scala 3 compiler team), the infrastructure is now in place for &lt;strong&gt;compiler checking of code samples&lt;/strong&gt; in the standard library Scaladoc and Scala 3 language. Many of the already-merged PRs take advantage of this new checking capability.&lt;/p&gt;

&lt;p&gt;The goals of the API doc work are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ensure all code samples in the documentation are &lt;strong&gt;checked by the compiler&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Ensure every class has at least &lt;strong&gt;basic class-level documentation&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Ensure every method has at least &lt;strong&gt;basic method-level documentation&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Make sure method-level documentation &lt;strong&gt;meets minimum standards&lt;/strong&gt; such as including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@param&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@return&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@throws&lt;/code&gt; annotations.&lt;/li&gt;
  &lt;li&gt;Further &lt;strong&gt;improve and expand&lt;/strong&gt; any especially important or especially low-quality documentation.&lt;/li&gt;
  &lt;li&gt;Strive for all documentation to include &lt;strong&gt;applied, practical examples&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-else-is-planned&quot;&gt;What else is planned?&lt;/h2&gt;

&lt;p&gt;We have chosen tasks that seem highest priority while also being feasible this year with the funding we have and suitable for the people we have available. After considering the community’s input, we’ve chosen the following work items for this year in &lt;strong&gt;roughly descending order of importance&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Essential&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Improve &lt;strong&gt;issue reporting&lt;/strong&gt; for documentation problems.&lt;/li&gt;
  &lt;li&gt;Reduce &lt;strong&gt;backlog of unhandled&lt;/strong&gt; PRs and issues on website repos.&lt;/li&gt;
  &lt;li&gt;Document what &lt;strong&gt;language features&lt;/strong&gt; debuted or progressed in what Scala versions.&lt;/li&gt;
  &lt;li&gt;Document all &lt;strong&gt;compiler options&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Also important&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Write a new guide on &lt;strong&gt;Scala/Java interoperability&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Write a new guide on &lt;strong&gt;the REPL and its features&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Revise language reference to &lt;strong&gt;center Scala 3&lt;/strong&gt; rather than centering 2-to-3 migration.&lt;/li&gt;
  &lt;li&gt;Update &lt;strong&gt;language tour&lt;/strong&gt; for Scala 3.&lt;/li&gt;
  &lt;li&gt;Ensure &lt;strong&gt;language reference&lt;/strong&gt; isn’t missing any features.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Be consistent&lt;/strong&gt; about where features are documented.&lt;/li&gt;
  &lt;li&gt;Update &lt;strong&gt;language specification&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If possible&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Add links&lt;/strong&gt; from beginner pages to in-depth docs.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Add links&lt;/strong&gt; from reference docs to language spec.&lt;/li&gt;
  &lt;li&gt;Adopt Martin’s &lt;strong&gt;“common Scala style”&lt;/strong&gt; proposal in examples.&lt;/li&gt;
  &lt;li&gt;Improve &lt;strong&gt;appearance and functionality of Scaladoc&lt;/strong&gt; pages.&lt;/li&gt;
  &lt;li&gt;Improve Scala 3 &lt;strong&gt;syntax highlighting&lt;/strong&gt; on websites.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course we can’t promise this will all get done, but we intend to at least make progress on the above.&lt;/p&gt;

&lt;p&gt;The brief descriptions are not completely self-explanatory. There is more information about all of these items in the following detailed forum post:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://contributors.scala-lang.org/t/scala-documentation-web-sites-what-should-be-improved/7354/35&quot;&gt;https://contributors.scala-lang.org/t/scala-documentation-web-sites-what-should-be-improved/7354/35&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here is an additional forum post in which we responded to the rest of the suggestions received and explain why they were not selected in this round:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://contributors.scala-lang.org/t/scala-documentation-web-sites-what-should-be-improved/7354/34&quot;&gt;https://contributors.scala-lang.org/t/scala-documentation-web-sites-what-should-be-improved/7354/34&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This second group of ideas remains open for volunteers to tackle. It’s also possible we might be able to address them in some future round of funding.&lt;/p&gt;

&lt;h2 id=&quot;participation&quot;&gt;Participation&lt;/h2&gt;

&lt;p&gt;Scala Center team members on the documentation project are: Seth Tisue (team lead), Bill Venners, Chua Chee Seng, Guillaume Martres. Others may get involved later.&lt;/p&gt;

&lt;p&gt;We welcome community participation as well.&lt;/p&gt;

&lt;p&gt;The Scala Center has been entrusted with coordinating the commissioned Scala work for the Sovereign Tech Fund. The Scala Center is an independent, not-for-profit center sponsored by &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;corporate members and individual backers like you&lt;/a&gt; to promote and facilitate Scala. If you would like to participate and/or see more of these types of efforts, please reach out to your manager to see if your company can donate engineering time or membership to the Scala Center.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;The Scala Center Fundraising Campaign&lt;/a&gt; for more details.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Scala 3.8.4 is now available!</title>
    <link href="https://www.scala-lang.org/news/3.8.4/"/>
    <updated>2026-06-05T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/news/release-notes-3.8.4</id>
    <content type="html">&lt;h2 id=&quot;release-highlights&quot;&gt;Release highlights&lt;/h2&gt;

&lt;h3 id=&quot;security-audit-fixes&quot;&gt;Security audit fixes&lt;/h3&gt;

&lt;p&gt;Scala 3.8.4 includes improvements and fixes for issues discovered during the &lt;a href=&quot;https://scala-lang.org/blog/2026/06/01/first-part-security-audit.html&quot;&gt;Scala codebase security audit&lt;/a&gt; carried out in collaboration with the Open Source Technology Improvement Fund and Quarkslab. Notable fixes in this release include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Hardened TASTy parsing to prevent infinite loops on maliciously crafted files (&lt;a href=&quot;https://github.com/scala/scala3/pull/25676&quot;&gt;#25676&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Fixed a stored XSS vulnerability in Scaladoc (&lt;a href=&quot;https://github.com/scala/scala3/pull/25681&quot;&gt;#25681&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Improved error handling in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.sys.process.Parser.tokenize&lt;/code&gt; (&lt;a href=&quot;https://github.com/scala/scala3/pull/25675&quot;&gt;#25675&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Fixed TastyPrinter’s JAR-walking logic to include subdirectories (&lt;a href=&quot;https://github.com/scala/scala3/pull/25678&quot;&gt;#25678&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;help-syntax-for-all-compiler-settings-26052&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:help&lt;/code&gt; syntax for all compiler settings (&lt;a href=&quot;https://github.com/scala/scala3/pull/26052&quot;&gt;#26052&lt;/a&gt;)&lt;/h3&gt;

&lt;p&gt;You can now append &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:help&lt;/code&gt; to any compiler setting to see its documentation — not just a fixed subset as before. This works wherever you pass compiler options, making it easier to discover available flags without leaving your workflow.&lt;/p&gt;

&lt;p&gt;With the Scala runner, add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:help&lt;/code&gt; to a flag on the command line when running a script or project:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; scala test.scala -Xkind-projector:help
-Xkind-projector  Allow `*` as type lambda placeholder to be compatible with
                  kind projector. When invoked as -Xkind-projector:underscores
                  will repurpose `_` to be a type parameter placeholder, this
                  will disable usage of underscore as a wildcard.
                  Default disable
                  Choices: disable, , underscores
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the REPL, pass the same flag through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:settings&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scala&amp;gt; :settings -Wunused:help
-Wunused  Enable or disable specific `unused` warnings
          Choices:
          - nowarn,
          - all,
          - imports :
                Warn if an import selector is not referenced.,
          - privates :
                Warn if a private member is unused,
          - locals :
                Warn if a local definition is unused,
          - explicits :
                Warn if an explicit parameter is unused,
          - implicits :
                Warn if an implicit parameter is unused,
          - params :
                Enable -Wunused:explicits,implicits,
          - patvars :
                Warn if a variable bound in a pattern is unused,
          - linted :
                Enable -Wunused:imports,privates,locals,implicits
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;upgrade-to-scala-cli-1140&quot;&gt;Upgrade to Scala CLI 1.14.0&lt;/h3&gt;

&lt;p&gt;The bundled Scala CLI has been upgraded from 1.11.x through 1.12.5, 1.13.0, to &lt;strong&gt;1.14.0&lt;/strong&gt;. Notable additions across these versions include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;v1.12.5:&lt;/strong&gt; experimental &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cross&lt;/code&gt; support for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doc&lt;/code&gt;; global &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--offline&lt;/code&gt; config key; experimental local &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.m2&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publish local&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;v1.13.0:&lt;/strong&gt; Scala.js 1.21.0 support; Ammonite REPL deprecated and scheduled for removal; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java-test-runner&lt;/code&gt; for pure Java tests; GraalVM native-image packaging via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;packaging.graalvmJvmId&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;packaging.graalvmArgs&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;v1.14.0:&lt;/strong&gt; support for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.test.java&lt;/code&gt; files; a toggle to turn auto-IDE-setup off&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See the &lt;a href=&quot;https://github.com/VirtusLab/scala-cli/releases/tag/v1.14.0&quot;&gt;Scala CLI release notes&lt;/a&gt; for full details.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;For the complete list of changes and contributor credits, see the &lt;a href=&quot;https://github.com/scala/scala3/releases/tag/3.8.4&quot;&gt;release notes on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Scala Codebase Security Audit Complete</title>
    <link href="https://www.scala-lang.org/blog/2026/06/01/first-part-security-audit.html"/>
    <updated>2026-06-01T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/blog/2026/06/01/first-part-security-audit</id>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post covers work done under the &lt;a href=&quot;https://www.scala-lang.org/blog/2026/01/27/sta-invests-in-scala.html&quot;&gt;Sovereign Tech Fund investment&lt;/a&gt; umbrella: &lt;a href=&quot;https://contributors.scala-lang.org/t/standard-library-now-open-for-improvements-and-suggestions/7337&quot;&gt;Maintenance of the Standard Library/Core Library Modules and APIs&lt;/a&gt;. The work is coordinated by the &lt;a href=&quot;https://scala.epfl.ch/&quot;&gt;Scala Center&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Scala Center is proud to share the first results of the security audit of Scala carried out in collaboration with &lt;a href=&quot;https://ostif.org/&quot;&gt;Open Source Technology Improvement Fund&lt;/a&gt; and the security researchers at &lt;a href=&quot;https://github.com/scala/scala-lang/blob/ddfc6996a8a1c66cc891261f57684a41ec5268b6/blog/_posts/2026-06-01-first-part-security-audit.md&quot;&gt;Quarkslab&lt;/a&gt;. The audit was divided into two major parts: an assessment of the Scala 3 compiler and Scala standard library codebases, and a separate review of Scala’s supply-chain security.&lt;/p&gt;

&lt;p&gt;This &lt;a href=&quot;https://ostif.org/wp-content/uploads/2026/05/26-01-2527-REP-scala-security-audit-V1.0.pdf&quot;&gt;first publication&lt;/a&gt; focuses on the compiler and standard library audit. Since many reported security issues in Scala ecosystems involve the standard library, the audit aimed to strengthen the security and robustness of Scala’s core components through a combination of manual code review and automated tooling, including fuzzing and Java deserialization gadget finders.&lt;/p&gt;

&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;

&lt;p&gt;Read the full report &lt;a href=&quot;https://ostif.org/wp-content/uploads/2026/05/26-01-2527-REP-scala-security-audit-V1.0.pdf&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;No critical or major security issues were identified during the audit. However, the review uncovered 5 medium severity issues, 1 low severity issue, and 2 informational findings, all of which have since been addressed by the Scala maintainers. All of these issues are fixed as of the date of this blog post, both for the 3.3 LTS branch and for the main 3.8 branch.&lt;/p&gt;

&lt;p&gt;Importantly, these issues do not affect typical users compiling Scala code locally or through continuous integration pipelines. Most findings were only relevant in scenarios where the Scala compiler is exposed as a service and processes untrusted input, where they could potentially lead to denial-of-service-type behavior.&lt;/p&gt;

&lt;h2 id=&quot;fixes&quot;&gt;Fixes&lt;/h2&gt;

&lt;p&gt;All reported issues were present in 3.8-RC1 and fixed before the publication of this blog post, both in the Scala 3.3 LTS branch and in the main Scala 3.8 development branch.&lt;/p&gt;

&lt;p&gt;One example was a medium severity issue in &lt;a href=&quot;https://github.com/scala/scala3/pull/25676&quot;&gt;the compiler’s handling of TASTy files&lt;/a&gt;. The compiler did not validate that certain offsets were nonnegative, which could lead to an infinite loop when processing a maliciously crafted TASTy file containing unexpected negative offsets. The fix introduced additional validation not only for this specific case, but more generally for parsing variable-length TASTy integers, helping prevent similar classes of issues in the future.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Severity&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Description&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Perimeter&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Fixes&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Medium&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.sys.Process.ProcessBuilderImpl.AbstractFunction0&lt;/code&gt; may be used as a deserialization gadget&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Standard library&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://github.com/scala/scala3/pull/25679&quot;&gt;Issue 25679&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Medium&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Stored XSS vulnerability&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Scaladoc (Scala 3.8-RC1)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://github.com/scala/scala3/pull/25681&quot;&gt;Issue 25681&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Medium&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Unexpected return value in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.collection.SeqOps.indexOfSlice&lt;/code&gt; on empty sequences&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Standard library&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Invalid, Scala behaves the same as other languages here.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Medium&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Uncaught &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ParseException&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.sys.process.Parser.tokenize&lt;/code&gt; on unmatched quotes&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Standard library&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://github.com/scala/scala3/pull/25675&quot;&gt;Issue 25675&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Medium&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Infinite loop during section loading in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dotty.tools.dotc.core.tasty.TastyUnpickler&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Compiler&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://github.com/scala/scala3/pull/25676&quot;&gt;Issue 25676&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Low&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Potential command injection in GitHub Action CI/CD scripts&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;GitHub Action workflows&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://github.com/scala/scala3/pull/25677&quot;&gt;Issue 25677&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Low&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Scala JVM bytecode could lead to conflicts between generated and user-defined methods&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Compiler&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Acceptable, no evidence it leads to any security issue.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Info&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Use of a non-cryptographically secure random number generator&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Compiler&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://github.com/scala/scala3/pull/25660&quot;&gt;Issue 25660&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Info&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TastyPrinter&lt;/code&gt; silently skips &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.tasty&lt;/code&gt; files in subdirectories of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.jar&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scalac -print-tasty&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://github.com/scala/scala3/pull/26082&quot;&gt;Issue 26082&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;how-to-report-future-security-issues&quot;&gt;How to report future security issues&lt;/h2&gt;

&lt;p&gt;Please let us know as soon as you discover a security issue as per &lt;a href=&quot;https://scala-lang.org/security/&quot;&gt;https://scala-lang.org/security/&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;thank-you&quot;&gt;Thank you&lt;/h2&gt;

&lt;p&gt;We first began discussions with the team at Open Source Technology Improvement Fund in July 2024. Between defining the scope of the audit, securing funding, assembling the teams, and carrying out the work itself, nearly two years passed before reaching this milestone.&lt;/p&gt;

&lt;p&gt;Projects like this are a reminder that open source work takes time, collaboration and coordination, patience and persistence, and countless contributions along the way.&lt;/p&gt;

&lt;p&gt;And so, we extend our gratitude to every person and organization involved in making this effort possible, including the Sovereign Tech Agency, the Open Source Technology Improvement Fund, Quarkslab, and the many Scala teams and maintainers who contributed along the way. We also look forward to sharing the final part of the audit, focused on Scala’s supply-chain security.&lt;/p&gt;

&lt;h2 id=&quot;participation&quot;&gt;Participation&lt;/h2&gt;

&lt;p&gt;The Scala Center has been entrusted with coordinating the commissioned Scala work for the Sovereign Tech Fund. The Scala Center is an independent, not-for-profit center sponsored by &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;corporate members and individual backers like you&lt;/a&gt; to promote and facilitate Scala. If you would like to participate and/or see more of these types of efforts, please reach out to your manager to see if your company can donate engineering time or membership to the Scala Center.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;The Scala Center Fundraising Campaign&lt;/a&gt; for more details.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Scala Days 2026: Call for proposals open</title>
    <link href="https://www.scala-lang.org/blog/2026/04/30/scala-days-2026-cfp.html"/>
    <updated>2026-04-30T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/blog/2026/04/30/scala-days-2026-cfp</id>
    <content type="html">&lt;h2 id=&quot;scala-days-2026-call-for-proposals-open&quot;&gt;&lt;strong&gt;Scala Days 2026: Call for proposals open&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;Submit your talk &lt;a href=&quot;https://cfp.scaladays.org/scala26/cfp&quot;&gt;https://cfp.scaladays.org/scala26/cfp&lt;/a&gt; and be part of Scala Days 2026!&lt;/p&gt;

&lt;p&gt;The Call for Proposals is now open and will close on May 31, 2026, at 23:59 CEST.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://scaladays.org/program-committee&quot;&gt;Program Committee&lt;/a&gt; is looking for talks, labs, and workshops that showcase how Scala is evolving and delivering value in today’s fast-changing technology landscape.&lt;/p&gt;

&lt;p&gt;In particular, we’re excited to hear practical insights, real-world experience reports, and forward-looking ideas.&lt;/p&gt;

&lt;p&gt;See the topics below for inspiration.&lt;/p&gt;

&lt;p&gt;Kind reminder: Super Early Bird tickets are available only until the end of the day on April 30, 2026.&lt;/p&gt;

&lt;h2 id=&quot;formats&quot;&gt;&lt;strong&gt;Formats&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;This year’s program includes three submission formats. &lt;strong&gt;Talks&lt;/strong&gt; and &lt;strong&gt;Interactive labs&lt;/strong&gt; are part of the main conference program, while &lt;strong&gt;Workshops&lt;/strong&gt; take place after the conference and require a separate ticket.&lt;/p&gt;

&lt;h3 id=&quot;talks-30-minutes&quot;&gt;&lt;strong&gt;Talks (30 minutes)&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Classic conference talks for sharing ideas, lessons learned, technical deep-dives, and real-world experience.&lt;/p&gt;

&lt;p&gt;We’re looking for talks that bring real value to the community: practical insights, innovative approaches, hard-earned lessons, or fresh perspectives on Scala and its ecosystem.&lt;/p&gt;

&lt;p&gt;We will select up to 48 talks, organized across 3 parallel tracks as part of the main conference program.&lt;/p&gt;

&lt;h3 id=&quot;interactive-labs-2-hours&quot;&gt;&lt;strong&gt;Interactive Labs (2 hours)&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Interactive labs are a new format at Scala Days 2026: small-group, highly interactive sessions built around live demos, guided exploration, and practical experimentation during the conference.&lt;/p&gt;

&lt;p&gt;This format is ideal for showcasing tools, libraries, frameworks, and new ideas in action. The goal is for participants to explore, experiment, and leave with practical experience they can immediately apply.&lt;/p&gt;

&lt;p&gt;Because sessions are limited to 2 hours total, proposals should be designed to get participants engaged quickly, with minimal setup time and a clear path into the core experience.&lt;/p&gt;

&lt;p&gt;Interactive labs are also a great fit for open-source maintainers who want to introduce their projects, onboard new users, and grow their contributor community.&lt;/p&gt;

&lt;p&gt;We will host up to 16 Interactive labs, organized into two dedicated conference time slots, across both days.&lt;/p&gt;

&lt;p&gt;Each session is limited to 10 participants, with seats allocated on a first-come, first-served basis.&lt;/p&gt;

&lt;h3 id=&quot;workshops-2-days&quot;&gt;&lt;strong&gt;Workshops (2 days)&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Workshops are in-depth training sessions held after the main conference, on October 14–15.&lt;/p&gt;

&lt;p&gt;Unlike Talks and Interactive labs, Workshops require a separate ticket and provide dedicated time for deeper exploration of a topic through practical exercises, discussion, and guided learning.&lt;/p&gt;

&lt;p&gt;They are designed to equip participants with substantial knowledge and practical experience over the course of two full days.&lt;/p&gt;

&lt;h2 id=&quot;topics&quot;&gt;&lt;strong&gt;Topics&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;These topics are intended as guidance, not limits. If your proposal is relevant to the Scala ecosystem, we want to hear it.&lt;/p&gt;

&lt;h3 id=&quot;experience--industry&quot;&gt;&lt;strong&gt;Experience &amp;amp; Industry&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Experience reports&lt;/li&gt;
  &lt;li&gt;Industrial adoption&lt;/li&gt;
  &lt;li&gt;Libraries and applications&lt;/li&gt;
  &lt;li&gt;Distributed systems&lt;/li&gt;
  &lt;li&gt;Scala-based contracts&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;data--ai&quot;&gt;&lt;strong&gt;Data &amp;amp; AI&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Machine learning in Scala&lt;/li&gt;
  &lt;li&gt;Big data&lt;/li&gt;
  &lt;li&gt;Scala in AI/ML pipelines&lt;/li&gt;
  &lt;li&gt;Integrating Scala with LLM-based systems&lt;/li&gt;
  &lt;li&gt;Scala’s role in data-centric and AI-driven architectures&lt;/li&gt;
  &lt;li&gt;Scala safety features for agentic systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;development&quot;&gt;&lt;strong&gt;Development&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Web development&lt;/li&gt;
  &lt;li&gt;Scala.js showcases&lt;/li&gt;
  &lt;li&gt;Game development&lt;/li&gt;
  &lt;li&gt;Native applications&lt;/li&gt;
  &lt;li&gt;Workflow and programming methodologies&lt;/li&gt;
  &lt;li&gt;Cloud and deployment&lt;/li&gt;
  &lt;li&gt;DevOps&lt;/li&gt;
  &lt;li&gt;Security&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;tooling&quot;&gt;&lt;strong&gt;Tooling&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Compilers and virtual machines&lt;/li&gt;
  &lt;li&gt;IDEs&lt;/li&gt;
  &lt;li&gt;Testing frameworks&lt;/li&gt;
  &lt;li&gt;Build tools&lt;/li&gt;
  &lt;li&gt;LLM-assisted development&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;foundations&quot;&gt;&lt;strong&gt;Foundations&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Functional programming&lt;/li&gt;
  &lt;li&gt;Type systems&lt;/li&gt;
  &lt;li&gt;Concurrency and parallelism&lt;/li&gt;
  &lt;li&gt;Algorithms and performance&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;community&quot;&gt;&lt;strong&gt;Community&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Open source&lt;/li&gt;
  &lt;li&gt;Teaching and mentoring&lt;/li&gt;
  &lt;li&gt;Community building&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;other-areas&quot;&gt;&lt;strong&gt;Other Areas&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Hardware&lt;/li&gt;
  &lt;li&gt;Networking&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;strategic--forward-looking-topics&quot;&gt;&lt;strong&gt;Strategic &amp;amp; Forward-Looking Topics&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Scala’s place in modern software ecosystems&lt;/li&gt;
  &lt;li&gt;How companies are using Scala in AI-driven environments&lt;/li&gt;
  &lt;li&gt;Adapting Scala to new architectural paradigms (data platforms, cloud-native, AI-first systems)&lt;/li&gt;
  &lt;li&gt;Real-world lessons from integrating Scala with emerging technologies&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;get-inspired&quot;&gt;&lt;strong&gt;Get inspired&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;Need inspiration? Explore talks from previous editions of Scala Days on the &lt;a href=&quot;https://www.youtube.com/@ScalaDaysConferences&quot;&gt;YouTube channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have questions or need help with your submission, contact us at &lt;strong&gt;info@scaladays.org&lt;/strong&gt;.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Last mile towards sbt 2</title>
    <link href="https://www.scala-lang.org/blog/2026/04/14/last-mile-towards-sbt2.html"/>
    <updated>2026-04-14T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/blog/2026/04/14/last-mile-towards-sbt2</id>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post covers work done under the &lt;a href=&quot;https://www.scala-lang.org/blog/2026/01/27/sta-invests-in-scala.html&quot;&gt;Sovereign Tech Fund investment&lt;/a&gt; umbrella: &lt;a href=&quot;https://contributors.scala-lang.org/t/sbt-2-production-ready-roadmap/7351&quot;&gt;sbt 2 Stable Release and Maintenance&lt;/a&gt;. The work is coordinated by the &lt;a href=&quot;https://scala.epfl.ch/&quot;&gt;Scala Center&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At conferences or on social media, the question we get most often is:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When is sbt 2 coming out?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We’ll discuss the plan in this post. But let’s go over the status first.&lt;/p&gt;

&lt;h2 id=&quot;whats-new-in-sbt-2&quot;&gt;What’s new in sbt 2?&lt;/h2&gt;

&lt;p&gt;sbt 2 is a new major version of sbt. If you’re familiar with sbt 1.x, hopefully the jump is not too far, but we have pushed sbt to a more modern standard. The headline features are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;sbt 2.x uses Scala 3.x (rather than Scala 2.12) for build definitions and plugins (Both sbt 1.x and 2.x are capable of building Scala 2.x and 3.x)&lt;/li&gt;
  &lt;li&gt;Embraces a simpler build.sbt via common settings&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; changed to an incremental test&lt;/li&gt;
  &lt;li&gt;Local and remote cache system that is Bazel-compatible&lt;/li&gt;
  &lt;li&gt;Uses sbtn (native-image client) for faster startup&lt;/li&gt;
  &lt;li&gt;Project matrix that can cross build subprojects in parallel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;
For more details, please check out the Scala Days 2025 talk &lt;a href=&quot;https://www.youtube.com/watch?v=GM2ywMb4z7A&quot;&gt;sbt 2.0: go big&lt;/a&gt; that I gave in August 2025.&lt;/p&gt;

&lt;p&gt;To share the progress thus far, we released the &lt;a href=&quot;https://eed3si9n.com/sbt-2.0-ideas&quot;&gt;sbt 2.0 ideas&lt;/a&gt; post in 2023, with sbt 2.0.0-alpha7. After a few more years of development, we released a beta version &lt;a href=&quot;https://eed3si9n.com/sbt-2.0.0-RC2&quot;&gt;sbt 2.0.0-RC2&lt;/a&gt; that’s ready for testing, around Scala Days 2025. Since then, we have been releasing more beta versions with both bug fixes and community-contributed feature enhancements. Perhaps surprising to some, sbt 2.x already started the binary compatibility from the RC series. This gave us a head start on repopulating the plugin ecosystem.&lt;/p&gt;

&lt;h2 id=&quot;repopulating-the-plugin-ecosystem&quot;&gt;Repopulating the plugin ecosystem&lt;/h2&gt;

&lt;p&gt;Thanks to the community effort, we already have &lt;a href=&quot;https://www.scala-sbt.org/2.x/docs/en/community-plugins.html&quot;&gt;60+ plugins&lt;/a&gt; ported to sbt 2.x. This is amazing for a build tool that hasn’t been released yet. Special thanks to Kenji Yoshida for pull requests, preparing and porting many plugins to sbt 2.&lt;/p&gt;

&lt;p&gt;Under the sbt 2 workstream, Anatolii from Scala Center has created &lt;a href=&quot;/blog/2026/03/02/sbt2-compat.html&quot;&gt;the sbt2-compat plugin&lt;/a&gt;, which bridges the source-level differences between sbt 1.x and 2.x. This allows cross-building of a plugin, aiding the migration process. Also under the STA workstream, Rikito Taniguchi from VirtusLab has created a pull request to &lt;a href=&quot;https://github.com/scala-js/scala-js/pull/5314&quot;&gt;cross build Scala.JS plugin to sbt 2.x (scala-js#5314)&lt;/a&gt;.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Plugin&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Version&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Published&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Notes&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Scala Native&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.5.11&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;sbt-assembly&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.3.1&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Play&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3.1.0-M9&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;⚠️&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Pending scripted tests.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Scala.JS&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;n/a&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;n/a&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Pending &lt;a href=&quot;https://github.com/scala-js/scala-js/pull/5314&quot;&gt;scala-js#5314&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Independently, the Play and Scala Native projects have been working towards sbt 2.x support as well.&lt;/p&gt;

&lt;h2 id=&quot;tooling-support-and-documentation&quot;&gt;Tooling support and documentation&lt;/h2&gt;

&lt;p&gt;Both IntelliJ Scala Plugin and Metals have published sbt plugins to import sbt 2.x projects.&lt;/p&gt;

&lt;p&gt;Documentation has been reorganized and partly rewritten as &lt;a href=&quot;https://www.scala-sbt.org/2.x/docs/en/&quot;&gt;The book of sbt&lt;/a&gt;, which has also been translated to &lt;a href=&quot;https://www.scala-sbt.org/2.x/docs/ja/&quot;&gt;Japanese&lt;/a&gt; and &lt;a href=&quot;https://www.scala-sbt.org/2.x/docs/zh-cn/&quot;&gt;Chinese&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;locking-down-to-20x-branch&quot;&gt;Locking down to 2.0.x branch&lt;/h2&gt;

&lt;p&gt;We have now created the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.0.x&lt;/code&gt; branch, so by default, all pull requests will target sbt 2.1. Only the critical bug fixes will be backported to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.0.x&lt;/code&gt; branch.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;On March 26, we released &lt;a href=&quot;https://eed3si9n.com/sbt-2.0.0-RC10&quot;&gt;sbt 2.0.0-RC10&lt;/a&gt;, kicking off the last mile process.&lt;/li&gt;
  &lt;li&gt;On April 7, we released &lt;a href=&quot;https://eed3si9n.com/sbt-2.0.0-RC11&quot;&gt;sbt 2.0.0-RC11&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;On April 13, we released &lt;a href=&quot;https://eed3si9n.com/sbt-2.0.0-RC12&quot;&gt;sbt 2.0.0-RC12&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Next steps&lt;/strong&gt;: Please try using &lt;a href=&quot;https://github.com/sbt/sbt/releases&quot;&gt;the latest RC&lt;/a&gt; on your projects, and check out the newly updated documentation. If you find bugs or missing documentation, please let us know by creating &lt;a href=&quot;https://github.com/sbt/sbt/issues&quot;&gt;an issue on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We will likely release a few more release candidates, but if no critical bugs are found, we will graduate one of them to the final release. So when is sbt 2 coming out? Depending on the bugs we discover, we are hopeful that it can happen in a few weeks to a few months.&lt;/p&gt;

&lt;h2 id=&quot;participation&quot;&gt;Participation&lt;/h2&gt;

&lt;p&gt;The Scala Center has been entrusted with coordinating the commissioned Scala work for the Sovereign Tech Fund. The Scala Center is an independent, not-for-profit center sponsored by &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;corporate members and individual backers like you&lt;/a&gt; to promote and facilitate Scala. If you would like to participate and/or see more of these types of efforts, please reach out to your manager to see if your company can donate engineering time or membership to the Scala Center.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;The Scala Center Fundraising Campaign&lt;/a&gt; for more details.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Fixing a Command Injection Vulnerability in sbt</title>
    <link href="https://www.scala-lang.org/blog/2026/03/31/sbt-security-advisory.html"/>
    <updated>2026-03-31T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/blog/2026/03/31/sbt-security-advisory</id>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post covers work done under the &lt;a href=&quot;https://www.scala-lang.org/blog/2026/01/27/sta-invests-in-scala.html&quot;&gt;Sovereign Tech Fund investment&lt;/a&gt; umbrella: &lt;a href=&quot;https://contributors.scala-lang.org/t/sbt-2-production-ready-roadmap/7351&quot;&gt;sbt 2 Stable Release and Maintenance&lt;/a&gt;. The work is coordinated by the &lt;a href=&quot;https://scala.epfl.ch/&quot;&gt;Scala Center&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As part of our ongoing work on the sbt 2 release, we’ve been reviewing and hardening core parts of the sbt codebase. During that work, we discovered a command injection vulnerability in how sbt resolves source dependencies on Windows. The issue has been assigned &lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2026-32948&quot;&gt;CVE-2026-32948&lt;/a&gt;, rated Moderate (CVSS 6.7), and is now fixed. If you use sbt on Windows, update to &lt;strong&gt;sbt 1.12.8&lt;/strong&gt; or &lt;strong&gt;sbt 2.0.0-RC10&lt;/strong&gt; or later to apply the fix.&lt;/p&gt;

&lt;h2 id=&quot;the-vulnerability&quot;&gt;The vulnerability&lt;/h2&gt;

&lt;p&gt;sbt has the &lt;a href=&quot;https://www.scala-sbt.org/1.x/docs/Multi-Project.html#Project+dependency&quot;&gt;source dependencies&lt;/a&gt; feature that lets you depend on a VCS repository in your build definition. For example, to depend on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;develop&lt;/code&gt; branch of a project published to GitHub:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dep&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RootProject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://github.com/sbt/io.git#develop&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When sbt resolves this, it clones the repository and checks out the branch specified in the URI fragment - the part after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt;. To do this, sbt runs a VCS client (git, hg, or svn) as an external process.&lt;/p&gt;

&lt;p&gt;On Windows, sbt historically wrapped these VCS commands in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd /c&lt;/code&gt; - routing them through the Windows command interpreter. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd.exe&lt;/code&gt; treats characters like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;&lt;/code&gt; as command separators. The URI fragment is user-controlled and was passed to VCS commands without any validation. This allows an attacker to break out of the intended git command and execute an arbitrary shell command on Windows.&lt;/p&gt;

&lt;p&gt;For example, consider a dependency declared as:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;vulnerable&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RootProject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://github.com/sbt/io.git#develop%26%26calc.exe&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%26%26&lt;/code&gt; decodes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt;. When this reaches &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd /c git checkout develop&amp;amp;&amp;amp;calc.exe&lt;/code&gt;, the command interpreter executes two commands: first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout develop&lt;/code&gt;, then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;calc.exe&lt;/code&gt;, starting the Windows Calculator.&lt;/p&gt;

&lt;p&gt;This is a classic &lt;a href=&quot;https://cwe.mitre.org/data/definitions/78.html&quot;&gt;OS command injection&lt;/a&gt; (CWE-78). The vulnerability has existed since sbt 0.9.5 and affects both the sbt 1.x line and sbt 2.0 release candidates on Windows.&lt;/p&gt;

&lt;h2 id=&quot;severity&quot;&gt;Severity&lt;/h2&gt;

&lt;p&gt;The severity is moderate because exploitation requires an attacker to actively build a project containing a malicious dependency URI, then requires a user to proactively build that project on their local machine. As sbt is a build tool, building a project carries an inherent risk of arbitrary command execution. As with any untrusted software, before building a project, you should check the source code, including the build file definitions.&lt;/p&gt;

&lt;p&gt;The threat model here is that a malicious attacker may try to inject commands disguised as a source dependency URL, and pass the code review because the behavior is unexpected.&lt;/p&gt;

&lt;h2 id=&quot;the-fix&quot;&gt;The fix&lt;/h2&gt;

&lt;p&gt;The primary fix was to stop routing VCS commands through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd /c&lt;/code&gt;. Git, Mercurial, and Subversion all ship as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.exe&lt;/code&gt; binaries on Windows. When Java’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProcessBuilder&lt;/code&gt; invokes an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.exe&lt;/code&gt; directly, arguments are passed as separate strings to the operating system - shell metacharacters are not interpreted. By removing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd /c&lt;/code&gt; wrapper, the injection vector disappears.&lt;/p&gt;

&lt;p&gt;As defense-in-depth, we also added input validation. URI fragments are now checked against an allowlist of characters - only alphanumeric characters, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; are allowed.&lt;/p&gt;

&lt;p&gt;Both measures follow established guidance from &lt;a href=&quot;https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html&quot;&gt;OWASP&lt;/a&gt;, &lt;a href=&quot;https://www.oracle.com/java/technologies/javase/seccodeguide.html&quot;&gt;Oracle’s Secure Coding Guidelines&lt;/a&gt;, and the &lt;a href=&quot;https://openjdk.org/jeps/8263697&quot;&gt;JEP 8263697 proposal&lt;/a&gt; for safer process launching.&lt;/p&gt;

&lt;p&gt;The fix is available in sbt 1.12.8 and sbt 2.0.0-RC10. The full advisory is published as &lt;a href=&quot;https://github.com/sbt/sbt/security/advisories/GHSA-x4ff-q6h8-v7gw&quot;&gt;GHSA-x4ff-q6h8-v7gw&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;workflow-of-applying-the-fix&quot;&gt;Workflow of applying the fix&lt;/h2&gt;

&lt;p&gt;One interesting detail to mention is that GitHub provides a &lt;a href=&quot;https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability&quot;&gt;way&lt;/a&gt; to report a vulnerability, work on the fix and submit a PR privately to prevent the vulnerability from being publicly disclosed before the fix is ready. If you encounter a security vulnerability in a Scala project, you should do the same, reporting it to the maintainers via Security Advisory on GitHub.&lt;/p&gt;

&lt;h2 id=&quot;applying-the-fix&quot;&gt;Applying the fix&lt;/h2&gt;

&lt;p&gt;Update your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project/build.properties&lt;/code&gt; to sbt 1.12.8 or later, or sbt 2.0.0-RC10 if you are using sbt 2. If your build uses source dependencies, verify that the URIs point to repositories you trust. In general, treat build definitions and VCS dependencies (including their build and source code) with the same review standards as application code. A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.sbt&lt;/code&gt; runs arbitrary Scala at build time and deserves the same scrutiny as any other code in your repository.&lt;/p&gt;

&lt;h2 id=&quot;participation&quot;&gt;Participation&lt;/h2&gt;

&lt;p&gt;The Scala Center has been entrusted with coordinating the commissioned Scala work for the Sovereign Tech Fund. The Scala Center is an independent, not-for-profit center sponsored by &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;corporate members and individual backers like you&lt;/a&gt; to promote and facilitate Scala. If you would like to participate and/or see more of these types of efforts, please reach out to your manager to see if your company can donate engineering time or membership to the Scala Center.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;The Scala Center Fundraising Campaign&lt;/a&gt; for more details.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Scala 3.8.3 is now available!</title>
    <link href="https://www.scala-lang.org/news/3.8.3/"/>
    <updated>2026-03-31T00:00:00+02:00</updated>
    <id>https://www.scala-lang.org/news/release-notes-3.8.3</id>
    <content type="html">&lt;h1 id=&quot;scala-383-is-now-available&quot;&gt;Scala 3.8.3 is now available!&lt;/h1&gt;

&lt;h2 id=&quot;release-highlights&quot;&gt;Release highlights&lt;/h2&gt;

&lt;h3 id=&quot;local-coverage-exclusions-with--coverage-off-blocks-24486&quot;&gt;Local coverage exclusions with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;// $COVERAGE-OFF$&lt;/code&gt; blocks (&lt;a href=&quot;https://github.com/scala/scala3/pull/24486&quot;&gt;#24486&lt;/a&gt;)&lt;/h3&gt;

&lt;p&gt;Coverage-instrumented builds can now disable coverage for a selected region of code, instead of excluding a whole file or class. This is useful for generated code, intentionally defensive branches, or support code that would otherwise distort coverage results.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using scala 3.8.3&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using options --coverage-out coverage-data&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Parser&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;input:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;toInt&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// $COVERAGE-OFF$&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;debugFallback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;zero&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// $COVERAGE-ON$&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@main&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CoverageTest&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;42&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Only the code between the markers is skipped by coverage instrumentation. The rest of the file is still measured as usual.&lt;/p&gt;

&lt;h3 id=&quot;safe-mode-for-capability-safe-code-25307&quot;&gt;Safe mode for capability-safe code (&lt;a href=&quot;https://github.com/scala/scala3/pull/25307&quot;&gt;#25307&lt;/a&gt;)&lt;/h3&gt;

&lt;p&gt;Scala 3.8.3 introduces &lt;strong&gt;safe mode&lt;/strong&gt;, a new experimental language subset that can be enabled with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import language.experimental.safe&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-language:experimental.safe&lt;/code&gt;. As described in the &lt;a href=&quot;https://www.scala-lang.org/api/3.8.3/docs/experimental/capture-checking/safe.html&quot;&gt;safe mode reference&lt;/a&gt;, this is not just “stricter capture checking”: it is a capability-safe subset intended for agent-generated or otherwise untrusted code.&lt;/p&gt;

&lt;p&gt;The underlying model is also described in the research paper &lt;a href=&quot;https://arxiv.org/abs/2603.00991&quot;&gt;Tracking Capabilities for Safer Agents&lt;/a&gt;, which proposes using Scala 3 with capture checking as a programming-language-based safety harness for AI agents.&lt;/p&gt;

&lt;p&gt;When safe mode is enabled, the compiler rejects unchecked casts and unchecked pattern matches, forbids escape hatches such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caps.unsafe&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@unchecked&lt;/code&gt;, and runtime reflection, turns on capture checking with mutation tracking, and restricts access to global APIs unless they are known-safe or explicitly reviewed.&lt;/p&gt;

&lt;p&gt;That last point is what makes the feature practical. Safe code is meant to call a restricted set of APIs directly, while effectful or implementation-dependent behavior can still be exposed through wrappers marked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@assumeSafe&lt;/code&gt;. The implementation in &lt;a href=&quot;https://github.com/scala/scala3/pull/25307&quot;&gt;#25307&lt;/a&gt; makes that boundary explicit: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@assumeSafe&lt;/code&gt; declarations are themselves written outside safe mode, and safe code calls them from within the restricted subset.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// app.scala&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using scala 3.8.3&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using file CheckedMailer.scala&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using options -experimental&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;language.experimental.safe&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PotentiallyUnsafeApp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EmailAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;team@scala-lang.org&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;CheckedMailer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// ok&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;             &lt;span class=&quot;c1&quot;&gt;// error: rejected in safe mode&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;asInstanceOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// error: rejected in safe mode&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EmailAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;???&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// error: rejected in safe mode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// CheckedMailer.scala&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scala.caps.assumeSafe&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@assumeSafe&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CheckedMailer&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;to:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EmailAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Sending message to $to&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;opaque&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EmailAddress&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;lt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EmailAddress&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;@assumeSafe&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;value:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EmailAddress&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;unapply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EmailAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the example above, the safe code in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app.scala&lt;/code&gt; can call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CheckedMailer.send&lt;/code&gt;, but the effectful operation is isolated behind an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@assumeSafe&lt;/code&gt; boundary. By contrast, direct calls to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;println&lt;/code&gt;, unchecked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asInstanceOf&lt;/code&gt; casts, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.caps.unsafe&lt;/code&gt; helpers are rejected in safe mode.&lt;/p&gt;

&lt;h3 id=&quot;scala-2-jvm-optimizer-ported-to-scala-3-25165&quot;&gt;Scala 2 JVM optimizer ported to Scala 3 (&lt;a href=&quot;https://github.com/scala/scala3/pull/25165&quot;&gt;#25165&lt;/a&gt;)&lt;/h3&gt;

&lt;p&gt;Scala 3 now includes the port of the Scala 2 JVM backend optimizer. The optimizer is opt-in: compiler flag &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-opt&lt;/code&gt; enables local bytecode optimizations, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-opt-inline:...&lt;/code&gt; controls which classes and packages may be inlined across call sites. This brings Scala 3 to feature parity with the Scala 2 optimizer and opens the door to performance gains for JVM applications.&lt;/p&gt;

&lt;p&gt;Rather than enabling blanket inlining everywhere, it is usually better to start from explicit filters. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-opt-inline&lt;/code&gt; setting accepts a comma-separated list of patterns; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;**&lt;/code&gt; matches all classes, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a.**&lt;/code&gt; matches a package and its subpackages, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;sources&amp;gt;&lt;/code&gt; matches classes compiled in the current run, and a leading &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; excludes matches. The last matching pattern wins.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using scala 3.8.3&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using options -opt&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using options &quot;-opt-inline:&amp;lt;sources&amp;gt;,my.app.**,!java.**,!org.example.**&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&amp;gt; using options &quot;-Wopt:at-inline-failed-summary,no-inline-missing-bytecode&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this configuration, the optimizer may inline code from the current compilation (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;sources&amp;gt;&lt;/code&gt;) and from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my.app&lt;/code&gt; subpackages defined in external dependencies, but not from the JDK or the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.example&lt;/code&gt; packages. This is often a good starting point for applications. For libraries, the conservative choice is usually to inline only from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;sources&amp;gt;&lt;/code&gt; or from packages you fully control.&lt;/p&gt;

&lt;p&gt;The optimizer port also brings additional settings:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Wopt:...&lt;/code&gt; enables optimizer warnings. Available choices are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;at-inline-failed-summary&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;at-inline-failed&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;any-inline-failed&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;no-inline-mixed&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;no-inline-missing-bytecode&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;no-inline-missing-attribute&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Yopt-specific:...&lt;/code&gt; enables individual optimization passes such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copy-propagation&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box-unbox&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nullness-tracking&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;closure-invocations&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;redundant-casts&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Yopt-inline-heuristics:default|everything|at-inline-annotated&lt;/code&gt; adjusts how aggressively the compiler chooses call sites for inlining&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Yopt-log-inline:&amp;lt;prefix&amp;gt;&lt;/code&gt; logs inliner activity for matching methods&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Yopt-trace:&amp;lt;prefix&amp;gt;&lt;/code&gt; traces optimizer progress for matching methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Wopt&lt;/code&gt; options let you choose between a one-line summary for failed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@inline&lt;/code&gt; calls, detailed per-callsite diagnostics, reporting for heuristic inlining failures, and warnings for cases where inlining could not even be decided because bytecode or Scala inline metadata was unavailable.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Y...&lt;/code&gt; optimizer flags are primarily intended for debugging and internal use. As with other &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Y&lt;/code&gt; settings, they are not stable user-facing interfaces, and their exact behavior may change between releases.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As with the Scala 2 optimizer, inlining external code comes with a compatibility trade-off: if you compile against one version of a dependency and later run against a different one, any inlined bytecode will not pick up the dependency’s runtime bug fixes or behavior changes. In practice, that means aggressive cross-library inlining is best reserved for applications with tightly controlled runtime classpaths. Read more about binary compatibility of optimized code in the &lt;a href=&quot;https://docs.scala-lang.org/overviews/compiler-options/optimizer.html#binary-compatibility&quot;&gt;Scala 2 optimizer documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The long-term plan is to build on this work in Scala 3.9 by enabling optimizations for the Scala standard library and the compiler itself.&lt;/p&gt;

&lt;h3 id=&quot;-print-lines-is-deprecated-for-removal-but-remains-accepted-as-a-no-op-25330&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-print-lines&lt;/code&gt; is deprecated for removal, but remains accepted as a no-op (&lt;a href=&quot;https://github.com/scala/scala3/pull/25330&quot;&gt;#25330&lt;/a&gt;)&lt;/h3&gt;

&lt;p&gt;Scala 3.8.3 restores the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-print-lines&lt;/code&gt; flag for compatibility, but only as a deprecated no-op. This avoids breaking existing builds in a patch release while giving users time to remove the setting from their build definitions.&lt;/p&gt;

&lt;p&gt;The flag no longer has any effect and is scheduled for removal in Scala 3.9.0.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;For the complete list of changes and contributor credits, see the &lt;a href=&quot;https://github.com/scala/scala3/releases/tag/3.8.3&quot;&gt;release notes on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Announcing Scala Days 2026</title>
    <link href="https://www.scala-lang.org/blog/2026/03/26/scala-days-2026.html"/>
    <updated>2026-03-26T00:00:00+01:00</updated>
    <id>https://www.scala-lang.org/blog/2026/03/26/scala-days-2026</id>
    <content type="html">&lt;p&gt;We are very happy to announce that the &lt;a href=&quot;https://scaladays.org/&quot;&gt;Scala Days 2026 conference&lt;/a&gt; will be taking place 12 - 13 October in Berlin, Germany, one of Europe’s most vibrant tech and open source hubs, known for its strong culture of collaboration and its growing role in advancing digital sovereignty through open technologies.&lt;/p&gt;

&lt;p&gt;Grab your &lt;a href=&quot;https://tickets.plainschwarz.com/scaladays26/&quot;&gt;Super Early Bird ticket&lt;/a&gt; and join us in Berlin this autumn!&lt;/p&gt;

&lt;h3 id=&quot;co-located-events&quot;&gt;Co-located events&lt;/h3&gt;

&lt;p&gt;Workshops will follow on 14–15 October, with various community-driven, co-located events taking place around the conference, possibly including the preceding weekend.&lt;/p&gt;

&lt;h3 id=&quot;meet-plain-schwarz&quot;&gt;Meet Plain Schwarz&lt;/h3&gt;

&lt;p&gt;For the Scala Days 2026 conference, the Scala Center partnered with Berlin-based company &lt;a href=&quot;https://plainschwarz.com&quot;&gt;Plain Schwarz&lt;/a&gt;, internationally renowned for organising conferences like Berlin Buzzwords and FOSS Backstage. Join us in welcoming Paul and the Plain Schwarz team to the Scala Days community as we work together on a refreshed and dynamic 2026 edition that stays true to Scala Days’ core spirit: business-driven and community-infused.&lt;/p&gt;

&lt;h3 id=&quot;call-to-action&quot;&gt;Call to action&lt;/h3&gt;

&lt;p&gt;Get your tickets at &lt;a href=&quot;https://tickets.plainschwarz.com/scaladays26/&quot;&gt;Super Early Bird&lt;/a&gt; price until April 9th, 23:55 CEST.&lt;/p&gt;

&lt;p&gt;Interested in sponsoring Scala Days 2026? Please inquire at &lt;a href=&quot;mailto:info@scaladays.org&quot;&gt;info@scaladays.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Follow us and share on &lt;a href=&quot;https://mastodon.social/@scaladays&quot;&gt;Mastodon&lt;/a&gt;, &lt;a href=&quot;https://bsky.app/profile/scaladays.org&quot;&gt;Bluesky&lt;/a&gt;, &lt;a href=&quot;https://www.linkedin.com/company/scala-center&quot;&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To get early updates and special offers, please sign up for the &lt;a href=&quot;https://plainschwarz.com/scala-days-2026-newsletter/&quot;&gt;mailing list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Join the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#scala-days&lt;/code&gt; channel on the &lt;a href=&quot;https://discord.com/invite/scala&quot;&gt;Scala Discord&lt;/a&gt; to chat with fellow attendees.&lt;/p&gt;

&lt;p&gt;Call for talk and workshop proposals opens late April 2026.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Porting the Scala 2 optimizer to Scala 3</title>
    <link href="https://www.scala-lang.org/blog/2026/03/23/porting-the-optimizer.html"/>
    <updated>2026-03-23T00:00:00+01:00</updated>
    <id>https://www.scala-lang.org/blog/2026/03/23/porting-the-optimizer</id>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post covers work done under the &lt;a href=&quot;https://www.scala-lang.org/blog/2026/01/27/sta-invests-in-scala.html&quot;&gt;Sovereign Tech Fund investment&lt;/a&gt; umbrella: &lt;a href=&quot;https://contributors.scala-lang.org/t/standard-library-now-open-for-improvements-and-suggestions/7337&quot;&gt;Maintenance of the Standard Library/Core Library Modules and APIs&lt;/a&gt;. The work is coordinated by the &lt;a href=&quot;https://scala.epfl.ch/&quot;&gt;Scala Center&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We are porting the &lt;em&gt;optimizer&lt;/em&gt; from the Scala 2 compiler to the Scala 3 compiler, improving the performance of Scala 3 applications without requiring developers to write more complex code. In early microbenchmarks of code written in a high-level functional style, we’re seeing 10-30% faster execution. But what exactly is this optimizer and why is it necessary?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This work is available as of version &lt;a href=&quot;https://github.com/scala/scala3/releases/tag/3.8.3-RC3&quot;&gt;3.8.3-RC3&lt;/a&gt; of the Scala compiler.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Scala is a modern and concise language, meaning you can write code expressing &lt;em&gt;what&lt;/em&gt; you want to do by composing primitives, rather than &lt;em&gt;how&lt;/em&gt; to do it step-by-step.
High-level code is easier to read and maintain, in addition to being shorter to write.&lt;/p&gt;

&lt;p&gt;Scala’s expressiveness enables you to write what you mean:&lt;/p&gt;
&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addOneMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;However, from a CPU’s point of view, a high-level API like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; is conceptually more complex than the equivalent low-level code.
It’s a function call that is passed another function, leading to a “&lt;a href=&quot;https://shipilev.net/jvm/anatomy-quarks/16-megamorphic-virtual-calls/&quot;&gt;megamorphic&lt;/a&gt;” call site that is harder for the JVM to optimize, and the function argument might need a closure to be allocated on the heap if it captures local values.
Compiled naïvely, the high-level call wouldn’t be as fast as this equivalent low-level loop:&lt;/p&gt;
&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addOneLoop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;length&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You don’t want to write this loop, because its purpose is a lot less obvious and it is harder to maintain, but without compiler help, you might have to write it if that function is critical to your application’s performance.
(Why would adding one to an array be critical to your app’s performance? Because you’re reading a pedagogical blog post and thus suspending disbelief!)&lt;/p&gt;

&lt;p&gt;If you’ve ever written a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; function yourself, you may recognize the loop above as being fairly close to how such a function is implemented, though the actual Scala implementation is a little more complex than you’d think because it needs to handle the mismatch between Scala’s generic array type and the JVM’s erased generics:&lt;/p&gt;
&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ct&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ClassTag&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;length&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;@unchecked&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;AnyRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;asInstanceOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]);&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;asInstanceOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]);&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* ... 7 cases omitted for brevity ...  */&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This method’s complexity is necessary to handle every possible array you can throw at it. You could also implement it with less code by using reflection to handle any possible array with just one code path, but that would lead to slower execution.
But in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addOne&lt;/code&gt; case, we only need the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array[Int]&lt;/code&gt; part. Type-checking the array isn’t needed, nor is casting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a(i)&lt;/code&gt; inside the loop, and the whole &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClassTag&lt;/code&gt; machinery could go away too.&lt;/p&gt;

&lt;h2 id=&quot;optimizing-for-the-best-of-both-worlds&quot;&gt;Optimizing for the best of both worlds&lt;/h2&gt;

&lt;p&gt;How can we get the best of both worlds? By having an &lt;em&gt;optimizer&lt;/em&gt; in the compiler that simplifies code and heuristically determines when it is beneficial to &lt;em&gt;inline&lt;/em&gt; code to enable further simplifications. Scala 2 has had such an optimizer for years now, &lt;a href=&quot;https://docs.scala-lang.org/overviews/compiler-options/optimizer.html&quot;&gt;as documented here&lt;/a&gt;, and it’s finally time to port it to Scala 3! Let’s see why it works in a little more detail.&lt;/p&gt;

&lt;p&gt;The optimizer takes care of turning our single-line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addOneMap&lt;/code&gt; example into our fast &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addOneLoop&lt;/code&gt; version. 
The key technique to perform this is &lt;em&gt;inlining&lt;/em&gt;: expanding the code of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; into the function where it is called.
This allows the optimizer to remove redundant branches and operations, such as removing the &lt;a href=&quot;https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html&quot;&gt;boxing&lt;/a&gt; of primitive types.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt; is simplified to just one of its branches, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asInstanceOf&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClassTag&lt;/code&gt; disappear, and we end up with the fast version.&lt;/p&gt;

&lt;p&gt;Inlining is powerful but can also have big drawbacks.
For starters, your CPU keeps frequently-executed code in an “instruction cache” that is very fast to access.
When common functions get bigger, fewer of them fit in that cache, so execution might become slower because fetching the code is slower even if the code itself has fewer function calls.&lt;/p&gt;

&lt;p&gt;Furthermore, inlining is not always possible.
A classic case is recursion: you cannot infinitely inline a function into itself.
Some more tricky problems include the fact that you cannot inline a method that accesses a class’s private fields outside of that class.
(At least not on the JVM, Scala.js does not have that problem.)&lt;/p&gt;

&lt;p&gt;In this case, there is a heuristic modeling the fact that if a function call uses a function literal as argument, inlining it is probably worth it.
There are other heuristics, such as one related to generic array operations in general, one that forces inlining of “forwarder” functions that merely call another function with minor changes to their arguments, and so on.&lt;/p&gt;

&lt;p&gt;The JVM already has an optimizer as part of Just-In-Time compilation, but it’s designed to make Java code fast, and typical Java code does not look like typical Scala code, so there are some important optimization opportunities not covered by the JVM’s optimizer.
Furthermore, the Scala compiler can optimize code at compile-time based on knowledge that is internal to the compiler and subject to change between versions, such as which Scala runtime functions are guaranteed to be pure or to always return non-null references.&lt;/p&gt;

&lt;p&gt;Early results show that for individual methods such as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addOne&lt;/code&gt; example above, the optimizer successfully turns the high-level version into an exact equivalent of the low-level one, which translates to 10-30% gains in some microbenchmarks.&lt;/p&gt;

&lt;h2 id=&quot;limitations&quot;&gt;Limitations&lt;/h2&gt;

&lt;p&gt;Heuristics mostly lead to better performance, but performance is such a complex topic that no set of heuristics can guarantee improvements.
It’s possible that enabling the optimizer on your specific codebase could regress some scenarios, which is why you should benchmark any performance-related change just as you would test any correctness-related change.
You can override the heuristics with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@inline&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@noinline&lt;/code&gt; annotations, but these should be a last-resort solution that you re-evaluate frequently as the compiler and the JVM improve.&lt;/p&gt;

&lt;p&gt;The other key limitation of the optimizer is that you can only use it if you know your dependencies at run-time are the same as the ones you had at compile time.
For instance, if you compile against library &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.example&lt;/code&gt; version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.3.6&lt;/code&gt;, and tomorrow the maintainers of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.example&lt;/code&gt; release version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.3.7&lt;/code&gt; that fixes a bug in a small function, this bugfix only has an effect on the already-deployed version of your code if it actually calls that function, not if the optimizer inlined the buggy version into your code.&lt;/p&gt;

&lt;p&gt;Thus, the optimizer targets &lt;em&gt;application&lt;/em&gt; code as well as the &lt;em&gt;standard library&lt;/em&gt;, and is an opt-in compiler setting.
You should only use it for &lt;em&gt;library&lt;/em&gt; code if you carefully select what inlining is allowed, as explained below.
Typically this means only inlining code within your own library, or within dependencies you control.&lt;/p&gt;

&lt;h2 id=&quot;using-the-optimizer&quot;&gt;Using the optimizer&lt;/h2&gt;

&lt;p&gt;Pass the flag &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-opt&lt;/code&gt; to the compiler to enable non-inlining optimizations, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-opt-inline:...&lt;/code&gt; arguments to enable inlining calls to specific packages.&lt;/p&gt;

&lt;p&gt;For instance, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-opt-inline:**,!java.**,!org.example.*&lt;/code&gt; tells the optimizer that inlining is allowed for all functions except those anywhere in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java&lt;/code&gt; package and those directly in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.example&lt;/code&gt; package.
More details are available with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-opt-inline:help&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;future-directions&quot;&gt;Future directions&lt;/h2&gt;

&lt;p&gt;Now that the optimizer is at feature parity with its Scala 2 incarnation, we hope to bring further optimizations to Scala 3.
For instance, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt;-based abstractions cannot always be fully eliminated today, but could with further work on the optimizer.
If you’re interested, you can contribute either by participating as described below, or by &lt;a href=&quot;https://github.com/scala/scala3/blob/main/CONTRIBUTING.md&quot;&gt;contributing&lt;/a&gt; to the compiler itself!&lt;/p&gt;

&lt;h2 id=&quot;participation&quot;&gt;Participation&lt;/h2&gt;

&lt;p&gt;The Scala Center has been entrusted with coordinating the commissioned Scala work for the Sovereign Tech Fund. The Scala Center is an independent, not-for-profit center sponsored by &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;corporate members and individual backers like you&lt;/a&gt; to promote and facilitate Scala. If you would like to participate and/or see more of these types of efforts, please reach out to your manager to see if your company can donate engineering time or membership to the Scala Center.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;The Scala Center Fundraising Campaign&lt;/a&gt; for more details.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Hardening Scoverage Support in Scala 3</title>
    <link href="https://www.scala-lang.org/blog/2026/03/11/scoverage.html"/>
    <updated>2026-03-11T00:00:00+01:00</updated>
    <id>https://www.scala-lang.org/blog/2026/03/11/scoverage</id>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post covers work done under the &lt;a href=&quot;https://www.scala-lang.org/blog/2026/01/27/sta-invests-in-scala.html&quot;&gt;Sovereign Tech Fund investment&lt;/a&gt; umbrella: &lt;a href=&quot;https://contributors.scala-lang.org/t/scoverage-hardening/7352&quot;&gt;Scoverage hardening&lt;/a&gt;. The work is coordinated by the &lt;a href=&quot;https://scala.epfl.ch/&quot;&gt;Scala Center&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Code coverage is a key part of maintaining high-quality Scala projects. We’ve recently made progress on making Scoverage more robust for Scala 3, expanding the way we test it and discovering and fixing new issues.&lt;/p&gt;

&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;

&lt;p&gt;Measuring how much of your Scala code is exercised by tests sounds simple until you try to do it yourself. That’s where code coverage tools come in. Code coverage is not optional for many organizations. As one of the QA metrics, coverage helps ensure reliability of the solution which is especially important in regulated sectors. Scoverage is the standard coverage tool for Scala, built directly into the Scala 3 compiler as a dedicated phase.&lt;/p&gt;

&lt;p&gt;A crucial requirement for Scoverage’s wide industry adoption is that Scoverage itself is reliable and well-tested. The tool is already tested via its own dedicated test suite - however, that is not enough. Most tricky bugs happen not in isolation but at intersections of language features. Therefore, Scoverage needs to be tested in interaction with all of the language features to be truly considered reliable. Furthermore, all future changes to the compiler should be tested in interaction with Scoverage to ensure the tool remains compatible with the compiler.&lt;/p&gt;

&lt;p&gt;To guarantee such a level of reliability, we have recently started a systematic rework of the testing strategy for Scoverage. This article reports on the progress we’ve made in 2026 so far.&lt;/p&gt;

&lt;h2 id=&quot;enabling-coverage-on-the-compiler-test-suite&quot;&gt;Enabling coverage on the compiler test suite&lt;/h2&gt;

&lt;p&gt;The first step was mapping out the current failures of Scoverage in interaction with other language features. The strategy for that was to enable Scoverage on the existing compiler test suite. This means, in addition to the usual CI run of the tests that we do for each new PR, now we run the same tests again, but with Scoverage enabled.&lt;/p&gt;

&lt;p&gt;Under this mode, for each test we verify three things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The compiler doesn’t crash&lt;/li&gt;
  &lt;li&gt;The coverage output file is produced&lt;/li&gt;
  &lt;li&gt;The coverage output file is valid and deserializable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, we have discovered &lt;em&gt;97 failing tests&lt;/em&gt; when coverage instrumentation was switched on. Those tests are being addressed in the order of impact. They were disabled for the time being to allow the validation logic to be merged early, thus future-proofing Scoverage.&lt;/p&gt;

&lt;p&gt;As for the rest of the tests, they are now running with coverage instrumentation for each PR, and passing them is a requirement for a PR to be merged to the compiler codebase. Furthermore, every newly added test to the compiler test suite is tested against Scoverage by default, thus preventing future PRs from unintentionally introducing Scoverage breakages.&lt;/p&gt;

&lt;p&gt;Details of this work are in &lt;a href=&quot;https://github.com/scala/scala3/pull/25009&quot;&gt;PR #25009&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;addressing-breakages-erased-values-and-the-purity-constraint&quot;&gt;Addressing breakages: erased values and the purity constraint&lt;/h2&gt;

&lt;p&gt;We have also taken the first steps to address discovered issues. A pattern that emerged is that failing tests were clustered around a few common root causes.&lt;/p&gt;

&lt;p&gt;One of the root causes behind a significant cluster of failures was the interaction between coverage instrumentation and Scala 3’s capability system. Capabilities in Scala 3 are represented as erased values - values that exist at compile time but are eliminated at runtime. Because they are erased, they must be pure: they cannot have side effects, and the compiler enforces this constraint, failing compilation if that is not the case.&lt;/p&gt;

&lt;p&gt;Coverage instrumentation works by injecting calls into the compiled code to record which expressions were executed. These calls introduce side effects. The erasure phase would then reject the result with an error.&lt;/p&gt;

&lt;p&gt;The fix is conceptually simple: the coverage instrumentation phase now checks whether a value is erased and, if so, skips it. &lt;em&gt;23 tests&lt;/em&gt; that previously failed under coverage are now passing as a result of this fix, opening the door to using Scoverage together with capabilities.&lt;/p&gt;

&lt;p&gt;Details in &lt;a href=&quot;https://github.com/scala/scala3/pull/25298&quot;&gt;PR #25298&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;expanding-the-testing-surface&quot;&gt;Expanding the testing surface&lt;/h2&gt;

&lt;p&gt;The Scala 3 compiler’s test suite is extensive. The strategy has been to enable coverage testing incrementally: start with the core tests, exclude the currently failing ones so regressions are caught from day one, then gradually expand the testing surface and fix discovered issues.&lt;/p&gt;

&lt;p&gt;The latest expansion of the testing surface was done after fixing the first cluster of issues. Coverage instrumentation is now also exercised on additional test suites such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rewrites&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;warn&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;explicit-nulls/pos&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;explicit-nulls/warn&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt; test suites. As a part of this expansion, we have discovered &lt;em&gt;13 new breakages&lt;/em&gt; that are being addressed in the same manner.&lt;/p&gt;

&lt;p&gt;Details in &lt;a href=&quot;https://github.com/scala/scala3/pull/25385&quot;&gt;PR #25385&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;To ensure the reliability of Scoverage in the industry, we are continuing to expand the testing surface of the tool and fix discovered issues. We will be sharing more updates as the work continues. If you are actively using Scoverage, your feedback is welcome! You can join the discussion on &lt;a href=&quot;https://contributors.scala-lang.org/t/scoverage-hardening/7352&quot;&gt;contributors.scala-lang.org&lt;/a&gt; or contribute Scoverage-related issues to the Scala 3 &lt;a href=&quot;https://github.com/scala/scala3/issues&quot;&gt;issue tracker&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;participation&quot;&gt;Participation&lt;/h2&gt;

&lt;p&gt;The Scala Center has been entrusted with coordinating the commissioned Scala work for the Sovereign Tech Fund. The Scala Center is an independent, not-for-profit center sponsored by &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;corporate members and individual backers like you&lt;/a&gt; to promote and facilitate Scala. If you would like to participate and/or see more of these types of efforts, please reach out to your manager to see if your company can donate engineering time or membership to the Scala Center.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;The Scala Center Fundraising Campaign&lt;/a&gt; for more details.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Migrating sbt plugins to sbt 2 with sbt2-compat plugin</title>
    <link href="https://www.scala-lang.org/blog/2026/03/02/sbt2-compat.html"/>
    <updated>2026-03-02T00:00:00+01:00</updated>
    <id>https://www.scala-lang.org/blog/2026/03/02/sbt2-compat</id>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post covers work done under the &lt;a href=&quot;https://www.scala-lang.org/blog/2026/01/27/sta-invests-in-scala.html&quot;&gt;Sovereign Tech Fund investment&lt;/a&gt; umbrella: &lt;a href=&quot;https://contributors.scala-lang.org/t/sbt-2-production-ready-roadmap/7351&quot;&gt;sbt 2 Stable Release and Maintenance&lt;/a&gt;. The work is coordinated by the &lt;a href=&quot;https://scala.epfl.ch/&quot;&gt;Scala Center&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There’s an ongoing, community-driven effort to repopulate the sbt plugin ecosystem in preparation for the sbt 2 release. From sbt 1.x, plugin authors can cross publish against sbt 2.0 release candidates. To facilitate the plugin migration, we’ve created the &lt;a href=&quot;https://github.com/sbt/sbt2-compat&quot;&gt;sbt2-compat plugin&lt;/a&gt;.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h2 id=&quot;the-plugincompat-pattern&quot;&gt;The PluginCompat Pattern&lt;/h2&gt;
&lt;p&gt;sbt 2 is a major upgrade from sbt 1 and makes breaking changes on the API level. As a plugin maintainer, you want to preserve compatibility with sbt 1 when migrating - so you want to cross-publish your plugin for sbt 1 and sbt 2. Ideally, you want to have the same codebase that compiles for both sbt 1 and sbt 2. However, due to the breaking changes to the API, this is not always possible. You end up with a situation where the same concept is expressed in a different way in sbt 1 and sbt 2.&lt;/p&gt;

&lt;p&gt;One such example is how files are represented in sbt 1 and sbt 2. In sbt 1, everything is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.io.File&lt;/code&gt;, whereas in sbt 2 the types are more granular depending on the context. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashedVirtualFileRef&lt;/code&gt; is used for classpath entries, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VirtualFile&lt;/code&gt; - for task outputs and caching artifacts, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VirtualFileRef&lt;/code&gt; - for path-like references. These types are defined in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xsbti&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;The current approach to handling these discrepancies is to have a single codebase that compiles for both sbt 1 and sbt 2, and use the &lt;a href=&quot;https://www.scala-sbt.org/2.x/docs/en/changes/migrating-from-sbt-1.x.html#the-plugincompat-technique&quot;&gt;PluginCompat pattern&lt;/a&gt; to provide a compatibility layer. For example, suppose you want to define a new task key that builds a JAR file and returns it.&lt;/p&gt;

&lt;p&gt;In sbt 1, you would define it as:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;taskKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;java.io.File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Builds a deployable JAR file&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In sbt 2, you would define it as:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;taskKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;xsbti.file.HashedVirtualFileRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Builds a deployable JAR file&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since you want to use the same codebase for both sbt 1 and sbt 2, you would need to abstract over the file type and define it separately for each sbt version. So:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/main/scala-2.12/PluginCompat.scala&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FileRef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;File&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// src/main/scala-3/PluginCompat.scala&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FileRef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xsbti&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;HashedVirtualFileRef&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You would then be able to define the task using this unified API:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;taskKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FileRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Builds a deployable JAR file&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This approach is a recurring pattern that you will encounter from plugin to plugin when attempting to cross-compile for sbt 1 and sbt 2. This is exactly the motivation behind the sbt2-compat plugin.&lt;/p&gt;

&lt;h2 id=&quot;cross-building-for-sbt-1-and-sbt-2-using-the-sbt2-compat-plugin&quot;&gt;Cross-building for sbt 1 and sbt 2 using the sbt2-compat plugin&lt;/h2&gt;
&lt;p&gt;The above encoding of the differences in the file API between sbt 1 and sbt 2 is already abstracted and ready to be reused in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt2-compat&lt;/code&gt; plugin. This plugin follows a similar pattern to the &lt;a href=&quot;https://github.com/dwijnand/sbt-compat&quot;&gt;sbt-compat&lt;/a&gt; plugin that handled cross-builds between sbt 0.x and 1.x. As a plugin maintainer, instead of manually defining the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PluginCompat.scala&lt;/code&gt; shim as described above, you would instead add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt2-compat&lt;/code&gt; plugin to your build and use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PluginCompat&lt;/code&gt; pattern as before, relying on the unified implementation provided by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt2-compat&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;1-add-sbt2-compat-to-your-plugin&quot;&gt;1. Add sbt2-compat to your plugin&lt;/h3&gt;

&lt;p&gt;Add the plugin in your plugin’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.sbt&lt;/code&gt; (&lt;strong&gt;not&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project/plugins.sbt&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;addSbtPlugin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;com.github.sbt&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sbt2-compat&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;version&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To cross-build for sbt 1 and sbt 2, see &lt;a href=&quot;https://www.scala-sbt.org/2.x/docs/en/changes/migrating-from-sbt-1.x.html#cross-building-sbt-plugins&quot;&gt;Cross building sbt plugins&lt;/a&gt; in the official migration guide.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;ThisBuild&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;crossScalaVersions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;3.8.1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.12.21&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;ThisBuild&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scalaVersion&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;crossScalaVersions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;head&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pluginCrossBuild&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sbtVersion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;scalaBinaryVersion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.12&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.12.3&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.0.0-RC9&quot;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For a concrete example, see &lt;a href=&quot;https://github.com/sbt/sbt-assembly/blob/1c2f9c5eb38f86abc9516d93ed1f1ccd5a76e374/build.sbt&quot;&gt;sbt-assembly&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;2-use-sbt2-compat-to-handle-the-api-differences-between-sbt-1-and-sbt-2&quot;&gt;2. Use sbt2-compat to handle the API differences between sbt 1 and sbt 2&lt;/h3&gt;

&lt;p&gt;Let’s take a look at how &lt;a href=&quot;https://github.com/sbt/sbt-assembly&quot;&gt;sbt-assembly&lt;/a&gt; uses sbt2-compat to cross-build for sbt 1 and sbt 2. Here is how it is applied:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Task keys&lt;/strong&gt; — Import &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileRef&lt;/code&gt; and use it for task return types. Notice how the type comes from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt2-compat&lt;/code&gt; plugin and does not need to be defined manually. (&lt;a href=&quot;https://github.com/sbt/sbt-assembly/blob/1c2f9c5eb38f86abc9516d93ed1f1ccd5a76e374/src/main/scala/sbtassembly/AssemblyKeys.scala#L10&quot;&gt;AssemblyKeys.scala L6–10&lt;/a&gt;):&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sbtcompat.PluginCompat.FileRef&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;assembly&lt;/span&gt;                  &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;taskKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FileRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Builds a deployable über JAR&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;assemblyPackageScala&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;taskKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FileRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Produces the Scala artifact&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;assemblyPackageDependency&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;taskKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FileRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Produces the dependency artifact&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;2. Shared logic&lt;/strong&gt; — Import compat helpers and use them for classpath handling, file conversion, and module metadata (&lt;a href=&quot;https://github.com/sbt/sbt-assembly/blob/1c2f9c5eb38f86abc9516d93ed1f1ccd5a76e374/src/main/scala/sbtassembly/Assembly.scala#L225-L294&quot;&gt;Assembly.scala L225–294&lt;/a&gt;):&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sbtcompat.PluginCompat.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;FileRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toNioPath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toFile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toOutput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toNioPaths&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toFiles&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;moduleIDStr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parseModuleIDStrAttribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Classpath iteration&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jars&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dirs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;classpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;toVector&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;sortBy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;toNioPath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;toAbsolutePath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;partition&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ClasspathUtil&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;isArchive&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toNioPath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Convert classpath entry to File for JarFile&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;jarFile&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JarFile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toFile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// ModuleID from metadata&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;jar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;moduleIDStr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parseModuleIDStrAttribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ModuleCoordinate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;organization&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;revision&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;getOrElse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ModuleCoordinate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;jar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;replaceAll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.jar&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Return task output&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;toOutput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;builtAssemblyJar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;3. Disabling task caching&lt;/strong&gt; — Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Def.uncached&lt;/code&gt; so classpath tasks read fresh values on sbt 2 (&lt;a href=&quot;https://github.com/sbt/sbt-assembly/blob/1c2f9c5eb38f86abc9516d93ed1f1ccd5a76e374/src/main/scala/sbtassembly/AssemblyPlugin.scala#L86-L87&quot;&gt;AssemblyPlugin.scala L86–87&lt;/a&gt;):&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sbtcompat.PluginCompat._&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fullClasspath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Def&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;uncached&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fullClasspath&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Runtime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fullClasspath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;externalDependencyClasspath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Def&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;uncached&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;externalDependencyClasspath&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Runtime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;externalDependencyClasspath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;project-status&quot;&gt;Project status&lt;/h2&gt;

&lt;p&gt;sbt2-compat currently covers the core API surface needed for cross-building plugins that work with files, classpaths, and packaging:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;sbt2-compat provides&lt;/th&gt;
      &lt;th&gt;Use for&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileRef&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Out&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArtifactPath&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Task key types, return types&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toNioPath&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toNioPaths&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toFile&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toOutput&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toFileRefsMapping&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toAttributedFiles&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Classpath and file conversion&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;moduleIDStr&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;artifactStr&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parseModuleIDStrAttribute&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parseArtifactStrAttribute&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Module metadata from classpath&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Def.uncached&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Opt out of sbt 2 task caching&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.name()&lt;/code&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileRef&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;File name (via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileRefOps&lt;/code&gt; on sbt 1)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toDirectCredentials&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;credentialForHost&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Credentials handling&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;createScopedKey&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setSetting&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;ScopedKey / settings API&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attributedPutFile&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attributedGetFile&lt;/code&gt;, etc.&lt;/td&gt;
      &lt;td&gt;Attributed metadata (typed vs string keys)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Plugin-specific compat (e.g. custom disk caching, test API differences, Scala stdlib bridges like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Streamable&lt;/code&gt;) stays in each plugin’s own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PluginCompat.scala&lt;/code&gt;. sbt-assembly, for instance, still maintains local shims for its cache, test settings, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PackageOption&lt;/code&gt; types. The sbt2-compat &lt;a href=&quot;https://github.com/sbt/sbt2-compat&quot;&gt;README&lt;/a&gt; documents this design and lists known caveats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development model.&lt;/strong&gt; sbt2-compat evolves iteratively by porting real-world plugins. Each port validates the existing API and may reveal missing compat methods. The idea is that as you port your plugins to sbt 2, you will discover gaps in the API that you can contribute back to sbt2-compat. For the exact development model, see the &lt;a href=&quot;https://github.com/sbt/sbt2-compat&quot;&gt;README&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contributions are welcome!&lt;/strong&gt; If you’re cross-building an sbt plugin for sbt 1 and sbt 2, the sbt 2 team would be happy to hear about your experiences! Share what worked, what didn’t, and what you wish sbt2-compat had. Pull requests with compat helpers that might help other plugins are welcome! You can share your experiences and participate in the discussion in the &lt;a href=&quot;https://contributors.scala-lang.org/t/sbt-2-production-ready-roadmap/7351&quot;&gt;sbt 2 production-ready roadmap&lt;/a&gt; thread at the Scala Contributors forum.&lt;/p&gt;

&lt;h2 id=&quot;participation&quot;&gt;Participation&lt;/h2&gt;

&lt;p&gt;The Scala Center has been entrusted with coordinating the commissioned Scala work for the Sovereign Tech Fund. The Scala Center is an independent, not-for-profit center sponsored by &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;corporate members and individual backers like you&lt;/a&gt; to promote and facilitate Scala. If you would like to participate and/or see more of these types of efforts, please reach out to your manager to see if your company can donate engineering time or membership to the Scala Center.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;/blog/2023/09/11/scala-center-fundraising.html&quot;&gt;The Scala Center Fundraising Campaign&lt;/a&gt; for more details.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Scala 3.8.2 is now available!</title>
    <link href="https://www.scala-lang.org/news/3.8.2/"/>
    <updated>2026-02-24T00:00:00+01:00</updated>
    <id>https://www.scala-lang.org/news/release-notes-3.8.2</id>
    <content type="html">&lt;h1 id=&quot;scala-382-is-now-available&quot;&gt;Scala 3.8.2 is now available!&lt;/h1&gt;

&lt;h2 id=&quot;release-highlights&quot;&gt;Release highlights&lt;/h2&gt;

&lt;h3 id=&quot;warning-for-for-with-many-vals-and-overloaded-map-25090&quot;&gt;Warning for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for&lt;/code&gt; with many &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val&lt;/code&gt;s and overloaded &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; (&lt;a href=&quot;https://github.com/scala/scala3/pull/25090&quot;&gt;#25090&lt;/a&gt;)&lt;/h3&gt;

&lt;p&gt;Scala 3.8’s &lt;strong&gt;betterFors&lt;/strong&gt; (available since 3.7 under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-preview&lt;/code&gt;) changes for-comprehension desugaring and removes an intermediate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; used for consecutive &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val&lt;/code&gt; bindings.&lt;/p&gt;

&lt;p&gt;The following code snippet behaves differently at runtime depending on Scala version used for compilation. In Scala 3.7.x and earlier it produces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List((43,29), (43,30), (43,31))&lt;/code&gt;, but starting with 3.8 it results in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Map(43 -&amp;gt; 31)&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Iterable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// warning: For comprehension with multiple val assignments may change result type&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;v&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Before (3.7):&lt;/strong&gt; A synthetic tuple-producing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; was inserted; that step could make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Map&lt;/code&gt; select a generic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; overload and become an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Iterable&lt;/code&gt; (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;In 3.8:&lt;/strong&gt; That synthetic step is removed, so the conversion no longer happens and a different &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt; path can be selected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The previous runtime behaviour can be achieved by explicitly converting first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Map&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Iterable&lt;/code&gt; type or by compilation with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-source:3.7&lt;/code&gt; settings.&lt;/p&gt;

&lt;p&gt;The new warning highlights code where this migration risk exists.&lt;/p&gt;

&lt;h2 id=&quot;notable-changes&quot;&gt;Notable changes&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:dep ...&lt;/code&gt; to add library dependencies in the Scala REPL &lt;a href=&quot;https://github.com/scala/scala3/pull/24131&quot;&gt;#24131&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Upgrade to Scala.js 1.20.2 &lt;a href=&quot;https://github.com/scala/scala3/pull/24898&quot;&gt;#24898&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Bump Scala CLI to v1.12.2 (was v1.11.0) &lt;a href=&quot;https://github.com/scala/scala3/pull/25217&quot;&gt;#25217&lt;/a&gt;:
New aliases for RC and nightly Scala versions.
See the Scala CLI release notes for additional details:
&lt;a href=&quot;https://github.com/VirtusLab/scala-cli/releases/tag/v1.12.0&quot;&gt;v1.12.0&lt;/a&gt;,
&lt;a href=&quot;https://github.com/VirtusLab/scala-cli/releases/tag/v1.12.1&quot;&gt;v1.12.1&lt;/a&gt; and
&lt;a href=&quot;https://github.com/VirtusLab/scala-cli/releases/tag/v1.12.2&quot;&gt;v1.12.2&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the complete list of changes and contributor credits, see the &lt;a href=&quot;https://github.com/scala/scala3/releases/tag/3.8.2&quot;&gt;release notes on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>State of the TASTy reader and Scala 2.13 ↔ Scala 3 compatibility</title>
    <link href="https://www.scala-lang.org/blog/state-of-tasty-reader.html"/>
    <updated>2026-02-20T00:00:00+01:00</updated>
    <id>https://www.scala-lang.org/blog/state-of-tasty-reader</id>
    <content type="html">&lt;p&gt;With the release of &lt;a href=&quot;https://scala-lang.org/news/3.8/&quot;&gt;Scala 3.8&lt;/a&gt;, Scala 2.13 and Scala 3 interoperability is no longer bidirectional.&lt;/p&gt;

&lt;p&gt;Every &lt;strong&gt;Scala 3 version supports consuming Scala 2.13&lt;/strong&gt; artifacts. There are no reasons or plans to change that state.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Scala 2.13 TASTy reader&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Ytasty-reader&lt;/code&gt;) remains useful for migrations and consuming Scala 3 artifacts, but it &lt;strong&gt;will never be able to consume Scala 3.8&lt;/strong&gt; and later artifacts. 
Scala 3.7 is the last minor version whose artifacts will remain consumable from Scala 2.&lt;/p&gt;

&lt;p&gt;This post summarizes the current state, the compatibility boundaries, and the recommended publishing strategy for teams that still need Scala 2.13 to consume Scala 3 libraries.&lt;/p&gt;

&lt;h2 id=&quot;what-is-the-tasty-reader&quot;&gt;What is the TASTy reader?&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.scala-lang.org/scala3/guides/tasty-overview.html&quot;&gt;TASTy&lt;/a&gt; (Typed Abstract Syntax Trees) is the high-level interchange format used by Scala 3.
Every Scala 3 compilation produces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.tasty&lt;/code&gt; files alongside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.class&lt;/code&gt; files.
While &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.class&lt;/code&gt; files lose type information due to JVM type erasure (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[String]&lt;/code&gt; becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[Object]&lt;/code&gt;), TASTy files preserve the complete type information — generic types, union types, intersection types, and more.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;TASTy reader&lt;/strong&gt; is a feature built into the Scala 2.13 compiler, enabled with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Ytasty-reader&lt;/code&gt; flag.
It allows a Scala 2.13 project to depend on libraries only published for Scala 3, by reading their &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.tasty&lt;/code&gt; files to reconstruct the precise type signatures that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.class&lt;/code&gt; files alone cannot convey.&lt;/p&gt;

&lt;p&gt;The TASTy reader was designed as a &lt;strong&gt;migration aid&lt;/strong&gt; — not a permanent compatibility layer.
It addressed a critical chicken-and-egg problem during the Scala 3 ecosystem bootstrap: library authors wanted to publish for Scala 3 but couldn’t abandon Scala 2.13 users, while application developers on Scala 2.13 couldn’t migrate until their dependencies were available.
The TASTy reader broke this deadlock by enabling a &lt;a href=&quot;https://www.scala-lang.org/blog/2020/11/19/scala-3-forward-compat.html#forward-compatibility&quot;&gt;forward-compatibility&lt;/a&gt; path, allowing Scala 2.13 projects to consume Scala 3-only libraries directly.&lt;/p&gt;

&lt;h2 id=&quot;technical-limitations-of-the-scala-2-tasty-reader&quot;&gt;Technical limitations of the Scala 2 TASTy reader&lt;/h2&gt;

&lt;p&gt;Even though both Scala 2 and Scala 3 share most of the language features, some features of each cannot be used by the other.
As an example, macros or existential types produced by Scala 2 cannot be represented or consumed by Scala 3.&lt;/p&gt;

&lt;p&gt;The Scala 2 TASTy reader is able to consume the Scala 3 TASTy format, but is not able to correctly represent an increasing amount of language features in a semantically correct way. Some of the unsupported features include:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inline&lt;/code&gt; (including Scala 3 macros)&lt;/li&gt;
  &lt;li&gt;Union types&lt;/li&gt;
  &lt;li&gt;Match types&lt;/li&gt;
  &lt;li&gt;Context functions&lt;/li&gt;
  &lt;li&gt;Polymorphic function types&lt;/li&gt;
  &lt;li&gt;Trait parameters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The classpath compatibility guide documents which Scala 3 features are or are not representable for Scala 2 consumption:
&lt;a href=&quot;https://docs.scala-lang.org/scala3/guides/migration/compatibility-classpath.html&quot;&gt;Scala 3 migration guide - classpath compatibility&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-changed-in-scala-38&quot;&gt;What changed in Scala 3.8&lt;/h2&gt;

&lt;p&gt;Scala 3.8 introduced a major ecosystem change by publishing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-library&lt;/code&gt; artifacts compiled using Scala 3, instead of reusing the Scala 2.13 standard library. As a result, it introduced a major new dependency that needs to be covered by the TASTy reader when consuming from Scala 2.&lt;/p&gt;

&lt;p&gt;What’s more, Scala 3 contained a mechanism to patch parts of the Standard Library to improve its performance, with its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala3-library_3&lt;/code&gt; replacements. One such example is &lt;a href=&quot;https://github.com/scala/scala3/blob/3.8.1/library/src/scala/Predef.scala#L314-L333&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.Predef.assert&lt;/code&gt;&lt;/a&gt;, defined as a normal method in Scala 2 but replaced with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transparent inline&lt;/code&gt; variant in Scala 3. Inlines are one of the features that Scala 2 cannot support.
Starting with Scala 3.8, this mechanism was removed and replaced with direct standard library modifications after ensuring both source and binary backward compatibility.&lt;/p&gt;

&lt;p&gt;The standard library of Scala 3 is now compiled with enabled support for explicit-nulls and capture-checking. Unless explicitly enabled, this change is not visible to users. However, at the TASTy level, each of these introduces additional features that cannot be represented in a Scala 2 compatible way: union types and capture checking.&lt;/p&gt;

&lt;p&gt;As a result, the old “Scala 2.13 ↔ Scala 3 sandwich” is no longer bidirectional at the classpath level.&lt;/p&gt;

&lt;h2 id=&quot;compile-classpath-incompatibilities&quot;&gt;Compile Classpath incompatibilities&lt;/h2&gt;

&lt;p&gt;Both Scala 2 and Scala 3 make strict assumptions about what’s available on the classpath and assume usage of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-library&lt;/code&gt; artifacts matching &lt;strong&gt;exactly&lt;/strong&gt; the version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-compiler&lt;/code&gt;. This is required for correct emission of references to members of the Scala Standard Library.
Usage of an incompatible version can lead to severe problems resulting in compilation crashes. On the Scala 2 side, it can trigger bytecode optimizer failures, as described in the &lt;a href=&quot;https://scala-lang.org/blog/post-mortem-3.8.0.html&quot;&gt;Scala 3.8.0 post-mortem&lt;/a&gt;. On the Scala 3 side, it can lead to &lt;a href=&quot;https://github.com/scala/scala3/issues/22890&quot;&gt;references to members not yet introduced&lt;/a&gt; or already removed from the actively developed standard library.
This requirement can easily be violated due to eviction rules of third-party dependencies and transitive dependencies on different versions of the Standard Library.&lt;/p&gt;

&lt;p&gt;Eviction of the Standard Library can also affect build tools. As an example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt&lt;/code&gt; has always ensured the use of matching versions of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-compiler&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-library&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-reflect&lt;/code&gt; to ensure their compatibility. Their perspective was recently documented in the sbt 1.12.3 release notes &lt;a href=&quot;https://eed3si9n.com/sbt-1.12.3#sm%C3%B8rrebr%C3%B8d---the-end-of-scala-213-3x-sandwich&quot;&gt;“Smørrebrød - the end of Scala 2.13-3.x sandwich”&lt;/a&gt;.
In that scenario, a Scala 2.13 project can pull in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-library:3.8.x&lt;/code&gt; through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for2_13Use3&lt;/code&gt;, while sbt still needs aligned Scala 2 compiler artifacts for the 2.13 side.
That leads resolution to attempt &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.scala-lang:scala-reflect:3.8.x&lt;/code&gt; (and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala-compiler:3.8.x&lt;/code&gt;), but these artifacts do not exist.
The result is the well-known sbt update error: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Error downloading org.scala-lang:scala-reflect:3.8.x&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;hard-compatibility-guarantee&quot;&gt;Hard compatibility guarantee&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Scala 3 consuming Scala 2.13 artifacts will remain supported for the foreseeable future.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That direction of compatibility is a hard requirement and remains part of the Scala 3 migration model.
The no-longer-supported direction is specifically Scala 2.13 consuming Scala 3.8+ artifacts through the TASTy reader.&lt;/p&gt;

&lt;h2 id=&quot;stable-tasty-reader-compatibility-scala-2136&quot;&gt;Stable TASTy reader compatibility (Scala 2.13.6+)&lt;/h2&gt;

&lt;p&gt;The table below starts at Scala 2.13.6 and covers stable, non-experimental TASTy support milestones.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Scala 2.13 release&lt;/th&gt;
      &lt;th&gt;Scala 3 minor version supported via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Ytasty-reader&lt;/code&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2.13.6&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2.13.7&lt;/td&gt;
      &lt;td&gt;3.1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2.13.9&lt;/td&gt;
      &lt;td&gt;3.2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2.13.11&lt;/td&gt;
      &lt;td&gt;3.3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2.13.13&lt;/td&gt;
      &lt;td&gt;3.4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2.13.15&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2.13.16&lt;/td&gt;
      &lt;td&gt;3.6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2.13.17&lt;/td&gt;
      &lt;td&gt;3.7&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Each Scala 2.13 release can consume artifacts from all Scala 3 versions up to and including the one listed in its row. For example, Scala 2.13.17 can consume artifacts published with Scala 3.0 through 3.7, but not forward-incompatible 3.8 or later. Intermediate Scala 2.13 releases between these milestones follow the most recent support level above.&lt;/p&gt;

&lt;h2 id=&quot;recommendations&quot;&gt;Recommendations&lt;/h2&gt;

&lt;h3 id=&quot;for-scala-213-users&quot;&gt;For Scala 2.13 users&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Keep TASTy-reader-based dependencies on versions published using Scala 3.7 or below.&lt;/li&gt;
  &lt;li&gt;Prefer dependencies published on Scala 3.3 LTS when available.&lt;/li&gt;
  &lt;li&gt;Plan migration of remaining Scala 2.13 modules to Scala 3 to remove reliance on the TASTy compatibility layer.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;for-scala-3-library-authors-supporting-scala-213-users&quot;&gt;For Scala 3 library authors supporting Scala 2.13 users&lt;/h3&gt;

&lt;p&gt;We recommend cross-compilation of libraries for Scala 2.13 and Scala 3 so that each series can be natively consumed.&lt;/p&gt;

&lt;p&gt;However, if that’s not possible we recommend for library authors:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Publish Scala 3 artifacts on &lt;strong&gt;Scala 3.3 LTS&lt;/strong&gt; for that compatibility path.&lt;/li&gt;
  &lt;li&gt;Scala 3.3 LTS will remain actively supported until at least Q2 2027 (at least one year after Scala 3.9 LTS is released), making it the safest choice for the transition period.&lt;/li&gt;
  &lt;li&gt;Prefer publishing library using Scala 3.3 LTS - Scala 3.7 is not expected to receive further releases. Use Scala 3 Next series only if access to their features features is necessary.&lt;/li&gt;
  &lt;li&gt;Plan and communicate potential dropping of Scala 2.13 support with the users, before migrating to Scala 3.9 LTS.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;The TASTy reader remains a migration bridge for Scala 2.13 with Scala 3.0 to 3.7 artifacts.
That bridge does not extend to Scala 3.8+ artifacts.&lt;/p&gt;

&lt;p&gt;At the same time, one direction is unchanged and guaranteed:
&lt;strong&gt;Scala 3 consuming Scala 2.13 artifacts is always supported.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For mixed ecosystems that still need Scala 2.13 consumers, Scala 3.3 LTS is the recommended publishing baseline, with newer lines used only when post-3.3 features are required.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Recap of Advent of Code 2025</title>
    <link href="https://www.scala-lang.org/blog/2026/02/12/advent-of-code-recap.html"/>
    <updated>2026-02-12T00:00:00+01:00</updated>
    <id>https://www.scala-lang.org/blog/2026/02/12/advent-of-code-recap</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://adventofcode.com/&quot;&gt;Advent of Code&lt;/a&gt;&lt;/strong&gt;, started by &lt;a href=&quot;http://was.tl/&quot;&gt;Eric Wastl&lt;/a&gt;, is an annual event providing daily programming puzzles between December 1st and December 12th.&lt;/p&gt;

&lt;p&gt;Let’s see how the Scala community participated in Advent of Code 2025. We were pleased by the strong engagement on both the &lt;a href=&quot;https://discord.com/invite/scala&quot;&gt;Scala Discord&lt;/a&gt; and on &lt;a href=&quot;https://scalacenter.github.io/scala-advent-of-code/2025/&quot;&gt;our solutions website&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;why-we-do-this&quot;&gt;Why we do this&lt;/h2&gt;

&lt;p&gt;At the &lt;a href=&quot;https://scala.epfl.ch&quot;&gt;Scala Center&lt;/a&gt;, we love writing code in Scala, and we hope you do too. One of our core priorities is to &lt;em&gt;communicate excitement about Scala&lt;/em&gt;, which motivates us to participate in the Advent of Code and share experiences solving problems with Scala with the wider programming community.&lt;/p&gt;

&lt;p&gt;Another key priority is to improve the &lt;em&gt;onboarding experience for newcomers&lt;/em&gt;. Part of that experience comes from the first impressions someone has reading Scala code. We hope that through hosting articles on &lt;a href=&quot;https://scalacenter.github.io/scala-advent-of-code/2025/&quot;&gt;our solutions website&lt;/a&gt;, newcomers can see that programming in Scala is an elegant way to solve problems.&lt;/p&gt;

&lt;h2 id=&quot;engagement-from-the-community&quot;&gt;Engagement from the community&lt;/h2&gt;

&lt;h3 id=&quot;discord-channel&quot;&gt;Discord channel&lt;/h3&gt;

&lt;p&gt;This year, there was lively conversation (with spoilers duly grayed out, of course!) in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#advent-of-code&lt;/code&gt; channel on the &lt;a href=&quot;https://discord.com/invite/scala&quot;&gt;Scala Discord server&lt;/a&gt;. Thank you to everyone who shared their code and/or helped each other come up with the best solutions. We especially thank those who offered friendly help to Scala newcomers.&lt;/p&gt;

&lt;h3 id=&quot;community-solutions&quot;&gt;Community solutions&lt;/h3&gt;

&lt;p&gt;106 solutions were submitted to &lt;a href=&quot;https://scalacenter.github.io/scala-advent-of-code/2025/&quot;&gt;the website&lt;/a&gt; this year, including some from first-time contributors.&lt;/p&gt;

&lt;p&gt;We give a special shout-out again this year to &lt;a href=&quot;https://github.com/AvaPL&quot;&gt;Paweł Cembaluk&lt;/a&gt;, who was the only participant to submit a solution for all 12 days.&lt;/p&gt;

&lt;h3 id=&quot;explainer-articles&quot;&gt;Explainer articles&lt;/h3&gt;

&lt;p&gt;As usual, we reached out to the community to help write the daily articles that show well-coded, well-explained solutions. The community organized a posting schedule which led to a full set of 12 complete articles. Thank you to all the authors who contributed. Each article has the author’s name at the top. The articles are on &lt;a href=&quot;https://scalacenter.github.io/scala-advent-of-code/2025/&quot;&gt;our solutions website&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;If you read this far, thank you again everyone for contributing to Scala and participating in Advent of Code, we hope you all had fun – and learned some things, too. See you in December 2026!&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Scala Standard Library Process</title>
    <link href="https://www.scala-lang.org/blog/2026/02/05/standard-library-process.html"/>
    <updated>2026-02-05T00:00:00+01:00</updated>
    <id>https://www.scala-lang.org/blog/2026/02/05/standard-library-process</id>
    <content type="html">&lt;h1 id=&quot;contributing-to-scala-standard-library&quot;&gt;Contributing to Scala Standard Library&lt;/h1&gt;

&lt;p&gt;After a long freeze, the Scala 3 standard library is again open to
contributions. The main place for contributing is now the
Scala 3 repository.&lt;/p&gt;

&lt;p&gt;Certain specific improvements might be eligible for backporting to Scala 2,
but this will be the exception rather than the norm. To
access most new functionality, you need to migrate to Scala 3.&lt;/p&gt;

&lt;h1 id=&quot;the-process&quot;&gt;The Process&lt;/h1&gt;

&lt;p&gt;The Scala 3 standard library is hosted in the
&lt;a href=&quot;https://github.com/scala/scala3&quot;&gt;scala/scala3&lt;/a&gt; repository. Any changes that
influence the standard library API should follow &lt;a href=&quot;https://github.com/scala/scala3/blob/main/docs/_docs/contributing/procedures/contributing-to-stdlib.md&quot;&gt;this process&lt;/a&gt;. If the changes are only internal, the process is 
the standard pull request one.&lt;/p&gt;

&lt;p&gt;The person responsible for coordinating the process is the Scala Core Coordinator. 
Current Coordinator can be found on the &lt;a href=&quot;https://www.scala-lang.org/scala-core/&quot;&gt;Scala Core Team page&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
</feed>
