diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-05-23 12:26:43 +0200 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-06-10 17:30:28 +0200 |
commit | 7046d73e2a1d88273a8382f27a4fb0af6f87db3b (patch) | |
tree | 14a2ea05fde37f519323647336f9f380b9beb70a /test/junit | |
parent | ddb29a8105bc3b692bc129cbd8ed111baae7076d (diff) | |
download | scala-7046d73e2a1d88273a8382f27a4fb0af6f87db3b.tar.gz scala-7046d73e2a1d88273a8382f27a4fb0af6f87db3b.tar.bz2 scala-7046d73e2a1d88273a8382f27a4fb0af6f87db3b.zip |
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 creates a fresh existential type symbol rather than
trying to use `narrow`.
I've included a unit test to show the sublteties of narrowing
refinment types.
Diffstat (limited to 'test/junit')
-rw-r--r-- | test/junit/scala/reflect/internal/TypesTest.scala | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/test/junit/scala/reflect/internal/TypesTest.scala b/test/junit/scala/reflect/internal/TypesTest.scala new file mode 100644 index 0000000000..95194ef0a4 --- /dev/null +++ b/test/junit/scala/reflect/internal/TypesTest.scala @@ -0,0 +1,35 @@ +package scala.reflect.internal + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import scala.tools.nsc.symtab.SymbolTableForUnitTesting + +@RunWith(classOf[JUnit4]) +class TypesTest { + + object symbolTable extends SymbolTableForUnitTesting + import symbolTable._, definitions._ + + @Test + def testRefinedTypeSI8611(): Unit = { + def stringNarrowed = StringTpe.narrow + assert(stringNarrowed != stringNarrowed) + assert(!(stringNarrowed =:= stringNarrowed)) + + def boolWithString = refinedType(BooleanTpe :: StringTpe :: Nil, NoSymbol) + assert(boolWithString != boolWithString) + assert(boolWithString =:= boolWithString) + + val boolWithString1 = boolWithString + val boolWithString1narrow1 = boolWithString1.narrow + val boolWithString1narrow2 = boolWithString1.narrow + // Two narrowings of the same refinement end up =:=. This was the root + // cause of SI-8611. See `narrowUniquely` in `Logic` for the workaround. + assert(boolWithString1narrow1 =:= boolWithString1narrow2) + val uniquelyNarrowed1 = refinedType(boolWithString1narrow1 :: Nil, NoSymbol) + val uniquelyNarrowed2 = refinedType(boolWithString1narrow2 :: Nil, NoSymbol) + assert(uniquelyNarrowed1 =:= uniquelyNarrowed2) + } +} |