improvement-proposals
improvement-proposals copied to clipboard
Match types amendment: extractors follow aliases and singletons
The existing spec uses as a legal example:
class Base {
type Y
}
type YExtractor[t] = Base { type Y = t }
And we are allowed to define:
type ExtractY[B <: Base] = B match
case YExtractor[t] => t
However, with the existing spec, extraction does not always work as one might expect:
class Sub1 extends Base:
type Y = Alias
type Alias = Int
class Sub2[T] extends Base:
type Y = T
class Sub3 extends Base:
val elem: Sub1 = new Sub1
type Y = elem.Y
ExtractY[Base { type Y = Int }] // OK
ExtractY[Sub1] // error
ExtractY[Sub2[Int]] // error
ExtractY[Sub3] // error
What's going on here is that when extracting a type Y from a non-stable prefix X, the spec mandates that we generate a skolem q and use that as a prefix to lookup the underlying type of Y. Extraction only succeeds if the underlying type does not refer to q. For example, for ExtractY[Sub1] we have q.Y with underlying type q.Alias which is rejected since it refers to q.
We amend the spec to follow aliases and singleton types in the extracted type, so that q.Alias can be dealiased to Int which is then accepted as a valid extracted type.
More motivating examples can be found in the implementation at https://github.com/scala/scala3/pull/20161.
I'm in favor of promoting this fix; amendments seem better to do sooner than later and it increases the power of match types, so I recommend voting yes to this at our next meeting.
I'm also in favor. Now that we have a spec, we can reason well about such changes. From my perspective, as long as it's sound and doesn't cause performance issues, any change that expands the match type capability is a welcome addition.
I agree with Bjoern and Oron. It's a logical generalization, and elsewhere in the compiler we implement similar behavior.