Open steinybot opened 3 years ago
I spent 10 or 15 minutes trying to minimize it further, but failed -- perhaps it really is minimized.
In particular, note that the problem goes away without the intermediary of the L
type alias.
Combining type aliases and existentials is often There Be Dragons territory in Scala 2, but I couldn't find an obvious duplicate ticket; a couple bugs that seem perhaps related: #10363, #8635
under Scala 2, javap shows the emitted signatures for childMethod
are:
Parent
: public abstract TwoTypeParam<?, ?> childMethod();
Child
: public OneTypeParam<?> childMethod();
whereas Scala 3(.0.0-RC2) emits:
Parent
: public abstract TwoTypeParam childMethod();
Child
: public OneTypeParam<?> childMethod();
Scala 3 emits a raw type, which seems surprising, and..... surely wrong?
I initially labeled this "fixed in Dotty" since Dotty accepts the code, but (as has emerged in conversation with Dale) and I think we should explore the possibility that both compilers are wrong to even allow this to compile.
In the Scala 3 case, the fact that it compiles because a raw type is involved (see previous comment) makes me even more suspicious about the whole thing. (But I have not gone digging in the Dotty tracker and/or codebase to see if this somehow considered normal.)
Here are my notes:
def childMethod: TwoTypeParam[A, B] forSome { type A; type B >: Nothing <: Any }
def childMethod: TwoTypeParam[A, B] forSome { type A; type B >: Any <: Any }
The first is parent's definition of childMethod
and the second is Child
's definition. I don't think Child's definition is a covariant-returning override, but an overload instead - because the existential type B
isn't equivalent. TL;DR I don't think it should compile.
Why do you expect this to not compile? OneTypeParam[_]
is a subtype of TwoTypeParam[_, _]
, and overrides are allowed to covariantly refine the result type. Also the type you get out of javap doesn't actually matter for Scala or the JVM, it's just the generic signature that javac will use, you need to use javap -v
to get the actual descriptor.
The issue here is that scala 2 is not emitting a bridge in Child for childMethod that returns TwoTypeParam, but scala 3 is.
Ahh, bridge methods, that didn't even occur to me.
If this working as intended in Scala 3, then I'm disinclined to dig any further on the Scala 2 side, but perhaps someone else will get interested.
OneTypeParam[_]
is a subtype ofTwoTypeParam[_, _]
If TwoTypeParam
were covariant in its second type parameter I could understand that. But otherwise how is Any =:= _
?
But otherwise how is Any =:= _?
That's just how wildcards work, any type which is within its bound is =:= to it, otherwise you couldn't pass an Array[Int]
to a method that accepts an Array[_]
for example.
That's just how wildcards work, any type which is within its bound is =:= to it, otherwise you couldn't pass an
Array[Int]
to a method that accepts anArray[_]
for example.
Ah, I see. And you can pass a Show[String]
as a Show[_]
(contravariance).
This thread is missing a good bridge pun, such as "A Bridge Too Far," "Bridge on the river Kwai," etc. Oh, "Bridges of Madison County." Also just "The Bridge" and "The Bridge at Remagen." An intrepid soul might venture into the territory of "Bridget Jones's Diary."
Just happened to notice Be a bridge for Christ while following Mina Choi.
So now I look at "bridge" and it looks so weird. How do you pronounce that? What is that strange word?
Is this one of those words from Dutch which are always weird? I remember the original series "The Bridge" was something Scandinavian. To require a bridge implies that you are already isolated somehow, "out there".
reproduction steps
Initially reported as https://github.com/scala-js/scala-js/issues/4454.
See reproduction here: https://github.com/steinybot/bug-reports/tree/scalajs/non-existent-method
using Scala 2.13.5
problem
This compiles and fails at runtime: