Confusing error message when type arguments are supplied to a higher kinded type
Compiler version
3.3.3 3.4.1
Minimized example
The example is minimized from a real life example using borer library.
The same error can be produced by using given instead of implicit, as shown in the commented out code.
object Main {
trait Wrap[X] {
def write(value: X): Unit
}
implicit def forMap[A, B, M[X, Y] <: Map[X, Y]]: Wrap[M[A, B]] = ???
//given givenForMap[A: Encoder, B: Encoder, M[X, Y] <: Map[X, Y]]: Wrap[M[A, B]] = ???
def main(args: Array[String]): Unit = {
val value = Map.empty[String, Int]
//val g = givenForMap[String, Int, Map[String, Int]]
//g.write(value)
val m = forMap[String, Int, Map[String, Int]]
m.write(value)
}
}
Output Error/Warning message
[error] -- [E007] Type Mismatch Error: C:\Dev\scala3compat\src\main\scala\Main.scala:18:12
[error] 18 | m.write(value)
[error] | ^^^^^
[error] | Found: (value : Map[String, Int])
[error] | Required: Map[String, Int][String, Int]
[error] |
Why this Error/Warning was not helpful
The type which is written as required is impossible to create.
When I remove the line m.write(value), much more sensible error is reported:
[error] 17 | val m = forMap[String, Int, Map[String, Int]]
[error] | ^
[error] | Type argument Map[String, Int] does not conform to upper bound Map
When compiling with Scala 2, the error is even more sensible:
[error] C:\Dev\scala3compat\src\main\scala\Main.scala:17:33: Map[String,Int] takes no type parameters, expected: 2
[error] val m = forMap[String, Int, Map[String, Int]]
Suggested improvement
The error should be diagnosed differently, so that it does not print an impossible type as required. Scala 2 seems to be more robust by not allowing to pass type arguments in a position where they are not expected.
I've just run into
def foo[F[_]](a: F[Int]): Unit = ()
foo[Null](null)
Error message
Found: Null
Required: Null[Int]
Note that implicit conversions were not tried because the result of an implicit conversion
must be more specific than Null[Int]
Explanation
===========
Tree: null
I tried to show that
Null
conforms to
Null[Int]
but none of the attempts shown below succeeded:
==> Null <: Null[Int] = false
The tests were made under a constraint with:
uninstantiated variables: T, T
constrained types: [T](x: T): T, [T](x: T): T
bounds:
T
T
ordering:
co-deps:
contra-deps:
as well as
def foo[F[_]](a: F[Int]): Unit = ()
foo[Null]
Error message
Found: (a : Null[Int])
Required: Null[Int]
Note that implicit conversions were not tried because the result of an implicit conversion
must be more specific than Null[Int]
Explanation
===========
Tree: a
I tried to show that
(a : Null[Int])
conforms to
Null[Int]
but none of the attempts shown below succeeded:
==> (a : Null[Int]) <: Null[Int] = false
The tests were made under a constraint with:
uninstantiated variables: T, T
constrained types: [T](x: T): T, [T](x: T): T
bounds:
T
T
ordering:
co-deps:
contra-deps:
which I believe is a further minimization of this issue. Both 3.3.4 and 3.5.1.