-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Binary compatibility and inline accessors #16983
Comments
I think it is interesting how Kotlin deals with that. They could have the same problem, but they solved it by requiring every symbol used from the inline function to be either public or have a
object C {
- @PublishedApi internal fun sth() = TODO()
+ fun sth() = TODO()
} is a safe and backward-compatible change. The benefit of doing it only through annotation and not automatically is that all symbols used from the inline functions are documented, so the maintainers know they have the same compatibility guarantees as public symbols. To solve our issue, I suggest taking inspiration from the Kotlin approach: The This still leaves object C:
- @api private def a: Int = 2
+ def a: Int = 2
} as an unsafe change breaking binary compatibility, but it is at least well documented. |
A possible solution would be to add a final class C:
@inlineAccessible private def a: Int = 2
def inline$a = a // generated by @inlineAccessible
inline def b: Int = a // use inline$a because a has @inlineAccessible We would also need to phase out the old inline accessor generation after this feature is added. We could start warning users when a dangerous inline accessor is generated. |
I forgot to click on |
Part of the fix for scala#16983
A possible problem with the annotation approach is how to make top-level objects accessible class C:
inline def f: Int = C.n
@inlineAccessible private object C:
def n: Int = 3 Not sure if a static method in |
We could take it a step further and decouple it from the But it then has other uses. In particular, it can be used for binary compatibility scenarios. If I want to make a public method private in a new version, I can mark it as |
Part of the fix for scala#16983
Part of the fix for scala#16983
Part of the fix for scala#16983
Part of the fix for scala#15413 Part of the fix for scala#16983
@sjrd how would class A:
@binaryAPI private val x = 1
inline def f = x
class B extends A:
@binaryAPI private val x = 2
inline def g = x We cannot make those definitions public or package private in the binary as they would clash. Maybe we don't allow those. |
Part of the fix for scala#15413 Part of the fix for scala#16983
That's a good point. I think we would have to refuse those, indeed. Not sure whether that makes sense 🤔 |
Part of the fix for scala#15413 Part of the fix for scala#16983
Part of the fix for scala#15413 Part of the fix for scala#16983
Part of the fix for scala#15413 Part of the fix for scala#16983
Part of the fix for scala#15413 Part of the fix for scala#16983
Part of the fix for scala#15413 Part of the fix for scala#16983
Part of the fix for scala#15413 Part of the fix for scala#16983
Part of the fix for scala#15413 Part of the fix for scala#16983
…ing flag (#18402) Introduces [SIP-52](scala/improvement-proposals#58) as an experimental feature. Fixes #16983 ### `@publicInBinary` A binary API is a definition that is annotated with `@publicInBinary` or overrides a definition annotated with `@publicInBinary`. This annotation can be placed on `def`, `val`, `lazy val`, `var`, `object`, and `given` definitions. A binary API will be publicly available in the bytecode. It cannot be used on `private`/`private[this]` definitions. #### Interaction with inline This is useful in combination with inline definitions. If an inline definition refers to a private/protected definition marked as `@publicInBinary` it does not need to use an accessor. We still generate the accessors for binary compatibility but do not use them. ### `-WunstableInlineAccessors` If the linting option `-WunstableInlineAccessors` is enabled, then a warning will be emitted if an inline accessor is generated. The warning will guide the user to the use of `@publicInBinary`.
Compiler version
3.0, 3.1, 3.2, 3.3
Inline accessors
Whenever we refer to a definition that is not public in an inline definition, we generate an inline accessor to access that definition from where the code is inlined.
is transformed into something like
Note that the accessors are added to the class using the private definition. This can lead to duplication of accessors.
Issue 1: Changing any definition from private to public is a binary incompatible change
This change would remove the need to generate
C$$inline$a
becausea
is publicly accessible. But any compiled code that inlinedb
before this change refers toC$$inline$a
. This code can be located in different libraries, and we might be unable to recompile it with the new inline definition.Issue 2: Changing the implementation of an inline definition can be a binary incompatible change
This change would remove the need to generate
C$$inline$a
because we never inlinea
. But any compiled code that inlinedb
before this change refers toC$$inline$a
. This code can be located in different libraries, and we might be unable to recompile it with the new inline definition.Issue 3: Removing
final
from a class is a binary incompatible changeIf the class is final
a
will get the accessorinline$a
but if it is not final it gets the accessorC$$inline$a
.The text was updated successfully, but these errors were encountered: