-
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
Nothing is inferred as the narrower type for unions in contravariant position #8834
Comments
Minimized example: trait Rec[-K] {
def foo[K0 <: K, K1]: Rec[K0] { type Foo[A <: K0] = Int } = ???
}
object Rec {
val r1: Rec[Int] = ???
val r2 = r1.foo
val r3: Rec[Int] = r2 // error: found Rec[Nothing], required: Req[Int]
} It works if the result type of foo is changed to use a type lambda explicitly: def foo[K0 <: K, K1]: Rec[K0] { type Foo <: [A <: K0] =>> Int } = ??? These two definitions should be equivalent but it looks like the first one is actually translated to: def foo[K0 <: K, K1]: Rec[K0] { type Foo >: [A <: K0] =>> Int <: [A <: K0] =>> Int } = ??? which means |
Wait no, they aren't, I confused it with the case where we only have an upper-bound: https://github.com/lampepfl/dotty/blob/c5a76f0db4c2908520a297414cf59a9a207fb11f/compiler/src/dotty/tools/dotc/core/Types.scala#L3629-L3633 In fact, trying to write this type in the definition of Rec itself leads to a variance error: trait Rec[-K] {
type Foo[A <: K] = Int // contravariant type K occurs in invariant position in type [A] = Int of type Foo
} So unless our handling of variance is incorrect, there's nothing we can do here. |
I mean, we could come up with some more complicated inference heuristics that would make the compiler choose the other bound when instantiating K0, but I can't think of any reasonable one (other than "avoid picking Nothing" which is an heuristic we try to avoid since it can also lead to issues) |
@smarter any reason Dotty thinks Both intuition and scalac seem to disagree: @ class A[-K]{type T[U<:K]}
defined class A
@ class A[-K]{type T[U>:K]}
cmd1.sc:1: contravariant type K occurs in covariant position in type >: K of type U
class A[-K]{type T[U>:K]}
^
Compilation Failed |
scalac agrees if you add a lower-bound or type alias for T: scala> class A[-K]{ type T[U >: K] = Int }
^
error: contravariant type K occurs in invariant position in type >: K of type U For Dotty, this expands to |
What do you mean by "scalac agrees"? The program in question had an upper bound, not a lower bound. The example you show was already in my message, to make a contrast with the lower bound case, which is accepted by scalac. My point is that scalac certainly does not agree that this is an invariant position for |
herm sorry, I meant to post: scala> class A[-K]{ type T[U <: K] = Int }
^
error: contravariant type K occurs in invariant position in type <: K of type U |
Minimized code
Output
Expectation
Expected it to compile without explicit annotations. This may be related to the deliberate restrictions on inferrence of unions in Dotty.
The text was updated successfully, but these errors were encountered: