scala/scala — pull request #3781 by retronym (2014-05-23 11:14:14+00:00)
Title: SI-8611 Avoid accidental patmat unification with refinement types

In the enclosed test, t8611a.scala, the patterns `O.{A, B}` were
incorrect treated as equivelent by the combination of
`uniqueTpForTree` and `Const.uniqueTpForTree`.

`uniqueTpForTree` used `Type#narrow` to try to create a distinct
type for each new pattern tree it encountered. However, narrowing a
`RefinedType` does not create a distinct type as we are used to
when narrowing, e.g. a class type.

// Type
def narrow: Type =
if (phase.erasedTypes) this
else {
val cowner = commonOwner(this)
refinedType(this :: Nil, cowner, EmptyScope, cowner.pos).narrow
}

// CompoundType
override def narrow: Type = typeSymbol.thisType

This commit first tries to use `narrow`, and then detects if the
result shares a type symbol with the input. If so, it compensates
by creating another refinement type over the result and narrows that.

I've included a unit test to show the sublteties of narrowing refinments.

Review by @adriaanm. I'm hoping you can find a less ugly way to do this!