Skip to content
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

Emit all classes as public to avoid object deserialization issues #14686

Merged
merged 1 commit into from
Mar 21, 2022

Conversation

smarter
Copy link
Member

@smarter smarter commented Mar 14, 2022

This aligns our behavior with Scala 2 and fixes the issue encountered in
typelevel/cats-effect#2360 (comment).

Alternatively, we could change ModuleSerializationProxy upstream to call
setAccessible(true) on the MODULE$ field, but this wouldn't work if the object
in question is inside a Java 9+ module.

@smarter
Copy link
Member Author

smarter commented Mar 14, 2022

For reference, all classes in Scala 2 are public in the backend because of this line: https://github.com/scala/scala/blob/ce95d6ca26179e5c189c2b1b40e68d4bc8738cfe/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala#L391

@smarter smarter force-pushed the emit-class-public branch from 13434c0 to 2f717a4 Compare March 14, 2022 16:21
@smarter
Copy link
Member Author

smarter commented Mar 14, 2022

Technically this isn't a forward-compatible ABI change, but since these classes aren't really part of our public API I think it's fine to ignore that:

Error:  scala3-library-bootstrapped: Failed binary compatibility check against org.scala-lang:scala3-library_3:3.1.1! Found 3 potential problems (filtered 697)
Error:   * private class scala.quoted.FromExpr#PrimitiveFromExpr is inaccessible in other version, it must be public.

@smarter smarter force-pushed the emit-class-public branch from 2f717a4 to fee60fb Compare March 14, 2022 18:15
@smarter smarter requested a review from sjrd March 14, 2022 18:15
smarter added a commit to dotty-staging/scalatest that referenced this pull request Mar 14, 2022
After scala/scala3#14686, Scala 3 emits all
classes (even local classes) as public, just like Scala 2. But unlike Scala 2,
the local class TestSpec in XmlSocketReporterSpec will be emitted with a
zero-argument constructor (in Scala 2 its constructor takes an
XmlSocketReporterSpec outer parameter which is never used which seems like a
bug). This matters because Scalatest considers a test suite "rerunnable" if it
has a zero argument public constructor. So to get the test suite to pass, we
need to check for the presence of this constructor just like SuiteRerunner does.
@smarter smarter force-pushed the emit-class-public branch from fee60fb to 86b239a Compare March 14, 2022 22:25
Comment on lines 299 to 302
// Classes are always emitted as public. This matches the behavior of Scala 2
// and is necessary for object deserialization to work properly, otherwise
// ModuleSerializationProxy may fail with an accessiblity error (see
// tests/run/serialize.scala).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps add a reference to the issue as well?

@sjrd
Copy link
Member

sjrd commented Mar 21, 2022

Technically this isn't a forward-compatible ABI change, but since these classes aren't really part of our public API I think it's fine to ignore that:

Yes, this is fine. It will also apply in libraries that have a forward compatibility policy, but in those libraries there should also only be a difference for Scala-private classes, which would be ignorable there as well.

@smarter smarter force-pushed the emit-class-public branch from 86b239a to 05dfcff Compare March 21, 2022 11:57
smarter added a commit to smarter/scalatest that referenced this pull request Mar 21, 2022
After scala/scala3#14686, Scala 3 emits all
classes (even local classes) as public, just like Scala 2. But unlike Scala 2,
the local class TestSpec in XmlSocketReporterSpec will be emitted with a
zero-argument constructor (in Scala 2 its constructor takes an
XmlSocketReporterSpec outer parameter which is never used which seems like a
bug). This matters because Scalatest considers a test suite "rerunnable" if it
has a zero argument public constructor. So to get the test suite to pass, we
need to check for the presence of this constructor just like SuiteRerunner does.
@smarter smarter enabled auto-merge March 21, 2022 12:01
smarter added a commit to dotty-staging/scalatest that referenced this pull request Mar 21, 2022
After scala/scala3#14686, Scala 3 emits all
classes (even local classes) as public, just like Scala 2. But unlike Scala 2,
the local class TestSpec in XmlSocketReporterSpec will be emitted with a
zero-argument constructor (in Scala 2 its constructor takes an
XmlSocketReporterSpec outer parameter which is never used which seems like a
bug). This matters because Scalatest considers a test suite "rerunnable" if it
has a zero argument public constructor. So to get the test suite to pass, we
need to check for the presence of this constructor just like SuiteRerunner does.
@smarter smarter force-pushed the emit-class-public branch from 05dfcff to 30961f5 Compare March 21, 2022 17:25
This aligns our behavior with Scala 2 and fixes the issue encountered in
typelevel/cats-effect#2360 (comment).

Alternatively, we could change ModuleSerializationProxy upstream to call
`setAccessible(true)` on the MODULE$ field, but this wouldn't work if the object
in question is inside a Java 9+ module.
@smarter smarter force-pushed the emit-class-public branch from 30961f5 to 5e6a3cf Compare March 21, 2022 20:17
@smarter smarter merged commit 1d13e17 into scala:main Mar 21, 2022
@smarter smarter deleted the emit-class-public branch March 21, 2022 21:54
nicolasstucki pushed a commit to dotty-staging/scalatest that referenced this pull request Mar 24, 2022
After scala/scala3#14686, Scala 3 emits all
classes (even local classes) as public, just like Scala 2. But unlike Scala 2,
the local class TestSpec in XmlSocketReporterSpec will be emitted with a
zero-argument constructor (in Scala 2 its constructor takes an
XmlSocketReporterSpec outer parameter which is never used which seems like a
bug). This matters because Scalatest considers a test suite "rerunnable" if it
has a zero argument public constructor. So to get the test suite to pass, we
need to check for the presence of this constructor just like SuiteRerunner does.
@Kordyjan Kordyjan added this to the 3.1.3 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants