Dotty: Match typing with trait types doesn't work

Created on 10 Mar 2020  路  4Comments  路  Source: lampepfl/dotty

minimized code

trait Foo; trait Bar

type Res[X] = X match {
  case Foo => String
  case Bar => Int
}

0: Res[Bar]

Compilation output

1 |0: Res[Bar]
  |^
  |Found:    (0 : Int)
  |Required: Res[Bar]

expectation

It works as expected if you change the traits to classes, or if you reverse the order of the cases.

bug

All 4 comments

That's working as intended. Reducing Res[Bar] to Int would be unsound, and once we merge #8024 it's going to be trivial to make a counter example. Given the Res type you defined above, the following typechecks (after #8024):

def res[X](x: X): Res[X] = x match {
  case _: Foo => String
  case _: Bar => Int
}

However, if Res[Bar] where to reduce to Int, we would be able to use multiple inheritence to get a class cast exception:

class Boom extends Foo with Bar
val i: Int = res[Boom](new Boom())
println(i + 1) //java.lang.ClassCastException: class String cannot be cast to Integer

If Foo and Bar are classes, the compiler knows that Foo and Bar are disjoint types, in which case it's fine to do the reduction. Likewise, if you swap the order of cases, reducing to Int is also OK given that Bar (the match type's scrutinee) is a subtype of Bar (the match type's first pattern).

@OlivierBlanvillain Hmm, makes sense, thanks. This means I can't ever expect matching on function types to be useful, right, since FunctionX is a trait? My original use case looked like this:

scala> type Res[F] = F match {
     |   case ((a, b) => t) => String
     |   case ( a     => t) => Int
     | }

scala> 0: Res[Int => Int]
1 |0: Res[Int => Int]
  |^
  |Found:    (0 : Int)
  |Required: Res[Int => Int]

Yes, matching on fonction types isn't going to lead to anywhere. In your example I don't think functions being traits is the problem, instead is has to do with variance. Any => Int is a subtype of both Int => Int and ((a, b) => t), so it would be wrong to reduce past the first case in your last example.

I know it's currently really hard to understand why certain match types don't reduce... I plan to invest time into better error messages for match types, in the worse case something 脿 la -Xlog-implicits should be relatively easy to implement.

@OlivierBlanvillain Just to clarify for the record, I don't need to distinguish Function1[Tuple2[a, b], t] and Function1[a, t], only Function1 and Function2, so I don't think variance is the issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

odersky picture odersky  路  71Comments

lihaoyi picture lihaoyi  路  30Comments

odersky picture odersky  路  45Comments

odersky picture odersky  路  60Comments

odersky picture odersky  路  114Comments