Closed
Description
For example:
class A
class B extends A
object Test {
val f1: A => Any = a => a
// This compiles
val f2: B => Any = f1
val f3: (a: A) => Any = a => a
// But this doesn't
val f4: (a: B) => Any = f3
}
Running with -explain-types
we get:
-- [E007] Type Mismatch Error: try/df.scala:11:26 ------------------------------
11 | val f4: (a: B) => Any = f3
| ^^
|Found: (a: A) => Any(Test.f3)
|Required: (a: B) => Any
|Constraint(
| uninstVars = ;
| constrained types =
| bounds =
| ordering =
|)
|Subtype trace:
| ==> (a: A) => Any(Test.f3) <:< (a: B) => Any
| ==> A => Any <:< B => Any LoApprox
| ==> scala.type(scala) <:< scala.type(scala)
| <== scala.type(scala) <:< scala.type(scala) = true
| ==> B <:< A
| ==> A <:< A LoApprox
| <== A <:< A LoApprox = true
| <== B <:< A = true
| ==> Any <:< Any
| <== Any <:< Any = true
| <== A => Any <:< B => Any LoApprox = true
| ==> (v1: A): Any <:< (a: A): Any frozen
| ==> Any <:< Any frozen
| <== Any <:< Any frozen = true
| <== (v1: A): Any <:< (a: A): Any frozen = true
| ==> hasMatchingMember((a: A) => Any(Test.f3) . apply, (a: B): Any), member = (v1: A): Any
| ==> (v1: A): Any <:< (a: A): Any frozen
| ==> Any <:< Any frozen
| <== Any <:< Any frozen = true
| <== (v1: A): Any <:< (a: A): Any frozen = true
| ==> (v1: A): Any <:< (a: B): Any
| <== (v1: A): Any <:< (a: B): Any = false
| <== hasMatchingMember((a: A) => Any(Test.f3) . apply, (a: B): Any), member = (v1: A): Any = false
| <== (a: A) => Any(Test.f3) <:< (a: B) => Any = false
In particular note (v1: A): Any <:< (a: B): Any = false
, this makes sense because when overriding a method in Scala, refining its term parameters contravariantly is not allowed, but dependent function types are encoded with a refined apply
method and this is not the behavior we want for them. It seems like we need some special-casing of dependent methods here. @odersky WDYT ?