-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #1747: Tweak for <:< between method types #1926
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
Conversation
If one of two method types originates from Java, the two types might match yet have different parameter signatures, because of the way Array[T] is handled differently in Java and Scala. The tweak takes this pecularity into account.
tests/pos/i1747.scala
Outdated
@@ -0,0 +1,3 @@ | |||
abstract class Coll[E] extends java.util.Collection[E] { | |||
def toArray[T](a: Array[T]): Array[T] = ??? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would probably be a good idea to make this a run
test to make sure that the erased signatures are also consistent in the bytecode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nicolasstucki Yes, I agree. Can I ask you to add this? Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that its sound to treat them as equivalent. You can't safely provide a generic Scala Array to Java:
scala> def foo[T](al: java.util.ArrayList[T], a: Array[T]) = al.toArray(a)
<console>:12: error: type mismatch;
found : Array[T]
required: Array[? with Object]
Note: T >: ? with Object, but class Array is invariant in type T.
You may wish to investigate a wildcard type such as `_ >: ? with Object`. (SLS 3.2.10)
def foo[T](al: java.util.ArrayList[T], a: Array[T]) = al.toArray(a)
^
You need to bound things to:
scala> def foo[T <: AnyRef](al: java.util.ArrayList[T], a: Array[T]) = al.toArray(a)
foo: [T <: AnyRef](al: java.util.ArrayList[T], a: Array[T])Array[T with Object]
The overriding method can't add a bound to the type parameter, but can express the restriction as:
abstract class C[E] extends java.util.Collection[E] {
override def toArray[T](a: Array[T with Object]): Array[T with Object] = ???
}
We also can't add bridges to paper over the difference because of the mutability of arrays.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, the pos
test is not testing anything as it is an abstract class and it could be defining new abstract members.
abstract class Coll[E] extends java.util.Collection[E] {
def toArray[T](a: Array[T]): Array[T] = ???
}
This is in fact generating the following method in the bytecode.
public Object toArray(Object a) { ... }
I added run tests that reproduce the issue (the CI will fail).
Yes |
If one of two method types originates from Java, the two
types might match yet have different parameter signatures,
because of the way Array[T] is handled differently in Java
and Scala. The tweak takes this pecularity into account.
Review by @nicolasstucki