Skip to content

Commit 986a872

Browse files
committed
Reorder NamedTuples with publicInBinary
1 parent 8f90c57 commit 986a872

File tree

1 file changed

+39
-38
lines changed

1 file changed

+39
-38
lines changed

_posts/2025-05-07-release-notes-3.7.0.md

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,47 +15,10 @@ We're excited to announce the release of Scala 3.7.0 — a significant minor rel
1515

1616
The [Scala Improvement Process (SIP)](https://docs.scala-lang.org/sips/) is how language changes and additions are made.
1717

18-
### [SIP-52: Binary APIs](https://docs.scala-lang.org/sips/binary-api.html)
19-
20-
For library maintainers, Scala 3.7.0 stabilizes the `@publicInBinary` annotation, introduced experimentally in Scala 3.4. This annotation ensures binary compatibility when inline methods access non-public members and prevent generation of redundant accessors required by inlining mechanism.
21-
22-
Inline methods are always inlined at their call sites. If they refer to members not visible outside their defining scope, the compiler generates accessor methods. The accessors are not subject to binary compatibility; they might be emitted differently by newer versions of compiler or eventually removed.
23-
The `@publicInBinary` annotation addresses this by emitting those members as public in bytecode, while maintaining restricted source-level visibility.
24-
This allows the compiler to refer to the original non-private member without the need to create additional accessors.
25-
26-
```scala
27-
object api:
28-
class Service:
29-
private[api] def implementation(): Unit = println("Executing old API")
30-
inline def use() = implementation()
31-
// generated by compiler, accessed in `use()`
32-
// def api$Service$$inline$implementation(): Unit = implementation()
33-
34-
class Consumer:
35-
inline def consume() = api.Service().implementation()
36-
// generated by compiler, accessed in `consume()`
37-
// def inline$implementation$i1(x$0: api$Service) = x$0.implementation()
38-
39-
@scala.annotation.publicInBinary
40-
private[api] var isActive: Boolean = false
41-
inline def isStale = !isActive
42-
```
43-
44-
The new annotation also resolves a long-standing issue with the inability to invoke a private constructor of a class from inlined methods. Now by annotating the constructor with `@publicInBinary` you are allowed to access it directly from inlined methods.
45-
46-
```scala
47-
import scala.annotation.publicInBinary
48-
49-
class Printer @publicInBinary private(id: Int)
50-
object Printer:
51-
inline def create(): Printer = new Printer(42) // Not allowed previously
52-
```
53-
54-
SIP-52 has also introduced the linting flag `-WunstableInlineAccessors` which detects and emits warnings for all unstable accessors generated for inline methods. This flag has been available since Scala 3.4.0. We highly recommend its usage of users' codebases, especially in the case of public libraries.
5518

5619
### [SIP-58: Named Tuples](https://docs.scala-lang.org/sips/named-tuples.html)
5720

58-
Named Tuples introduced as experimental in Scala 3.5 are now a stable feature.
21+
Named Tuples, introduced as experimental in Scala 3.5, are now a stable feature.
5922
Named tuples are a convenient lightweight way to return multiple results from a function or to model the data using tuples while allowing you to use meaningful names for its fields.
6023

6124
```scala
@@ -115,6 +78,44 @@ case class Release(version: String, issues: List[String])
11578
assert(query.issues.isEmpty)
11679
```
11780

81+
### [SIP-52: Binary APIs](https://docs.scala-lang.org/sips/binary-api.html)
82+
83+
For library maintainers, Scala 3.7.0 stabilizes the `@publicInBinary` annotation, introduced experimentally in Scala 3.4. This annotation ensures binary compatibility when inline methods access non-public members and prevent generation of redundant accessors required by inlining mechanism.
84+
85+
Inline methods are always inlined at their call sites. If they refer to members not visible outside their defining scope, the compiler generates accessor methods. The accessors are not subject to binary compatibility; they might be emitted differently by newer versions of compiler or eventually removed.
86+
The `@publicInBinary` annotation addresses this by emitting those members as public in bytecode, while maintaining restricted source-level visibility.
87+
This allows the compiler to refer to the original non-private member without the need to create additional accessors.
88+
89+
```scala
90+
object api:
91+
class Service:
92+
private[api] def implementation(): Unit = println("Executing old API")
93+
inline def use() = implementation()
94+
// generated by compiler, accessed in `use()`
95+
// def api$Service$$inline$implementation(): Unit = implementation()
96+
97+
class Consumer:
98+
inline def consume() = api.Service().implementation()
99+
// generated by compiler, accessed in `consume()`
100+
// def inline$implementation$i1(x$0: api$Service) = x$0.implementation()
101+
102+
@scala.annotation.publicInBinary
103+
private[api] var isActive: Boolean = false
104+
inline def isStale = !isActive
105+
```
106+
107+
The new annotation also resolves a long-standing issue with the inability to invoke a private constructor of a class from inlined methods. Now by annotating the constructor with `@publicInBinary` you are allowed to access it directly from inlined methods.
108+
109+
```scala
110+
import scala.annotation.publicInBinary
111+
112+
class Printer @publicInBinary private(id: Int)
113+
object Printer:
114+
inline def create(): Printer = new Printer(42) // Not allowed previously
115+
```
116+
117+
SIP-52 has also introduced the linting flag `-WunstableInlineAccessors` which detects and emits warnings for all unstable accessors generated for inline methods. This flag has been available since Scala 3.4.0. We highly recommend its usage of users' codebases, especially in the case of public libraries.
118+
118119
## Preview features
119120

120121
Scala 3.7 introduces the concept of `preview` features — fully implemented and SIP-approved, but potentially subject to small refinements before becoming stable.

0 commit comments

Comments
 (0)