-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #8001: Erase polymorphic value classes like Scala 2 #10765
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
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
395c27b
to
41ffe0c
Compare
Previously given: class Poly[A](val value: A) extends AnyVal We always erased `Poly[X]` to `Object`, no matter the value `X`, because the erasure was the erased underlying type as seen from its definition, and not as seen from the current prefix. But it turns out that in Scala 2, `Foo[Int]` will be erased to `Integer` instead (it would have made more sense to use `int` but I suspect this is more accidental than designed). To be binary-compatible with Scala 2 and to support the same kind of overloads we need to replicate its behavior, more precisely the rules I was able to reverse-engineer are: - Given `class Foo[A](x: A) extends AnyVal`, `Foo[X]` should erase like `X`, except if its a primitive in which case it erases to the boxed version of this primitive. - Given `class Bar[A](x: Array[A]) extends AnyVal`, `Bar[X]` will be erased like `Array[A]` as seen from its definition site, no matter the `X` (same if `A` is bounded). I was able to adapt our implementation of value class erasure to these new rules without too much refactoring through one compromise: a value class can no longer wrap another value class. This was never supported by Scala 2 so we can afford to not support it either.
41ffe0c
to
723c7b5
Compare
it probably doesn't add much new as a test case but i noticed this erases differently on Scala 2 vs Dotty object Values {
def reify[I <: Int with Singleton](implicit I: ValueOf[I]): I = valueOf[I]
} |
@bishabosha erasure of intersection types is something I'll address in another PR. |
I've removed the singleton bound and its the same result, object Values {
//public <I extends java.lang.Object> I reify(I);
// descriptor: (Ljava/lang/Object;)I
def reify[I <: Int](implicit I: ValueOf[I]): I = valueOf[I]
} |
3e898f7
to
d59f341
Compare
OK, that should be covered by |
7cdb761
to
f6cb41f
Compare
After the previous commit, this randomly fails the CI with "class defined twice module class scala" and I don't want to add more special cases to support this, instead we should probably just disallow `scala` as a top-level classname.
This test printed an error message in the log output which was extremely misleading since it looked like a weird test failure. Removing it instead of fixing it because it's not actually testing anything useful: it's supposed to check that we don't get a cascade of error messages if scala3-library is missing from the classpath, but after 24eb6cf this only worked by chance because the code we're compiling is extremely simple (Foo.scala only contains "class Foo"), so it's doubly misleading.
3c4d607
to
4727f44
Compare
odersky
approved these changes
Dec 14, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Previously given:
We always erased
Poly[X]
toObject
, no matter the valueX
, becausethe erasure was the erased underlying type as seen from its definition,
and not as seen from the current prefix. But it turns out that in Scala
2,
Foo[Int]
will be erased toInteger
instead (it would have mademore sense to use
int
but I suspect this is more accidental thandesigned).
To be binary-compatible with Scala 2 and to support the same kind of
overloads we need to replicate its behavior, more precisely the rules I
was able to reverse-engineer are:
class Foo[A](x: A) extends AnyVal
,Foo[X]
should erase likeX
, except if its a primitive in which case it erases to the boxedversion of this primitive.
class Bar[A](x: Array[A]) extends AnyVal
,Bar[X]
will beerased like
Array[A]
as seen from its definition site, no matterthe
X
(same ifA
is bounded).I was able to adapt our implementation of value class erasure to these
new rules without too much refactoring through one compromise: a value
class can no longer wrap another value class. This was never supported
by Scala 2 so we can afford to not support it either.