Shouldn`t this work? Should i file a bug report?


#1

The following code snipped does not compile, but I think it should.

sealed trait HasSome{
type SomeType
val someVal: SomeType
}
class HasInts(i:Int) extends HasSome{
type SomeType = Int
val someVal=i
}
def getSome(v:HasSome): v.SomeType = v match{
case i: HasInts => i.someVal
}

Why is the compiler of the opinion that i.SomeType does not conform to v.SomeType? Do I miss something or is this more like a bug?
Thanks in Advance for any input!


#2

i.SomeType is Int and v.SomeType may be anything, for example, String.


#3

I think it’s a limitation. It’s obvious that v eq i, but that information is not leveraged in the pattern match.

It’s not true that the pattern match is totally dumb about the type pattern, because surprisingly this compiles:

  def getMore(v: HasInts): v.SomeType = v match {
    case x: HasSome => x.someVal
  }

presumably because the type test is trivial. It isn’t using (x: HasSome).someVal.

Hash tag pattern matching is magic, except for case classes.


#4

The pattern has an explicit type ascription i: HasInts. It would be rather strange to infer a different type for i than the one that was explicitly requested by the user. I’m surprised that your version compiles, it’s probably a bug (as you noted, due to the trivial type test that can be removed).


#5

Inside the pattern match, the compiler “loses” the information, that i is of the same type as v.
I’m not sure if this is a bug. I’d argue that the spec covers this in 8.1.2:

A typed pattern x:T consists of a pattern variable x and a type pattern T. The type of x is the type pattern T, where each type variable and wildcard is replaced by a fresh, unknown type.

So as far as I understand it, it says the pattern variable only has the type specified in the pattern. But this also means, you can change your pattern to not lose the relevant information:

def getSome(v:HasSome): v.SomeType = v match{
    case i: HasInts with v.type => v.someVal
}

This way the compiler knows that i is also of v's type and therefore i.SomeType is v.SomeType.


#6

That’s a nice idea! (I went with a cast.)

It results in a non-exhaustive warning. That’s too bad, but it’s better than an error. I’d still call it a limitation.

Maybe the answer to the OP’s question, whether to file a bug report, is Yes, but then the question is, Which one?