Closed
Description
Minimized code
The example here, https://dotty.epfl.ch/docs/reference/new-types/match-types.html#dependent-typing fails when 3.1 is enabled. I'm posting this as a bug, because it's not clear to me how to make it work. Reproducing the code here, the match type definition works fine:
type LeafElem[X] = X match
case String => Char
case Array[t] => LeafElem[t]
case Iterable[t] => LeafElem[t]
case AnyVal => X
But the method doesn't:
def leafElem[X](x: X): LeafElem[X] = x match
case x: String => x.charAt(0)
case x: Array[t] => leafElem(x(9))
case x: Iterable[t] => leafElem(x.next())
case x: AnyVal => x
The error messages are these:
2 | case x: String => x.charAt(0)
| ^^^^^^
| pattern selector should be an instance of Matchable,
| but it has unmatchable type X instead
3 | case x: Array[t] => leafElem(x(9))
| ^^^^^^^^
| pattern selector should be an instance of Matchable,
| but it has unmatchable type X instead
4 | case x: Iterable[t] => leafElem(x.next())
| ^^^^^^^^^^^
| pattern selector should be an instance of Matchable,
| but it has unmatchable type X instead
5 | case x: AnyVal => x
| ^^^^^^
| pattern selector should be an instance of Matchable,
| but it has unmatchable type X instead
4 | case x: Iterable[t] => leafElem(x.next())
| ^^^^^^
|value next is not a member of X & Iterable[t] - did you mean x.head?
|
|where: X is a type in method leafElem with bounds >: (?1 : Iterable[t])
(There's also a bug in the Iterable
line; it doesn't like x.next()
. Using x.head
does work...)
Adding a bound to X
reduces the problem to the Array
and Iterable
lines:
scala> def leafElem[X <: Matchable](x: X): LeafElem[X] = x match
| case x: String => x.charAt(0)
| case x: Array[t] => leafElem(x(9))
| case x: Iterable[t] => leafElem(x.head)
| case x: AnyVal => x
|
3 | case x: Array[t] => leafElem(x(9))
| ^^^^
| value should be an instance of Matchable,
| but it has unmatchable type t instead
4 | case x: Iterable[t] => leafElem(x.head)
| ^^^^^^
| value should be an instance of Matchable,
| but it has unmatchable type t instead
I've tried various ways to fix those warnings, like the following, which fail for different reasons:
def leafElem[X <: Matchable, X2 <: Matchable](x: X): LeafElem[X] = x match
case x: String => x.charAt(0)
case x: Array[X2] => leafElem(x(9))
case x: Iterable[X2] => leafElem(x.head)
case x: AnyVal => x
def leafElem[X <: Matchable](x: X): LeafElem[X] = x match
case x: String => x.charAt(0)
case x: Array[t <: Matchable] => leafElem(x(9))
case x: Iterable[t <: Matchable] => leafElem(x.head)
case x: AnyVal => x
Output
Inline above.
Expectation
Defining leafElem
would be as straightforward as it is with Scala 3.0 flexibility.