aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-02-14 13:49:57 +0100
committerMartin Odersky <odersky@gmail.com>2014-02-14 13:49:57 +0100
commit28e9bb7c3f551265c7de671cc9eccc39bd2697de (patch)
treefc8102df37b5b70808c614ba6b2466352e4a61ab
parente1d53f03dc2d59e72fffde86919cac5462e7fd36 (diff)
downloaddotty-28e9bb7c3f551265c7de671cc9eccc39bd2697de.tar.gz
dotty-28e9bb7c3f551265c7de671cc9eccc39bd2697de.tar.bz2
dotty-28e9bb7c3f551265c7de671cc9eccc39bd2697de.zip
Avoid forming And/Or types with equal operands.
This can happen in particular in derivedAnd/Or type, when applying a substitution or other mapping which identifies two types that were different before.
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala2
-rw-r--r--src/dotty/tools/dotc/core/Types.scala20
2 files changed, 12 insertions, 10 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index c21e70eda..777ac0f3a 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -371,7 +371,7 @@ class TypeComparer(initctx: Context) extends DotClass {
val sd = tp1.denot.asSingleDenotation
def derivedRef(tp: Type) =
NamedType(tp1.prefix, tp1.name, sd.derivedSingleDenotation(sd.symbol, tp))
- secondTry(OrType(derivedRef(tp11), derivedRef(tp12)), tp2)
+ secondTry(OrType.make(derivedRef(tp11), derivedRef(tp12)), tp2)
case TypeBounds(lo1, hi1) =>
if ((tp1.symbol is GADTFlexType) && !isSubTypeWhenFrozen(hi1, tp2))
trySetType(tp1, TypeBounds(lo1, hi1 & tp2))
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index bacbe4f9d..c3b2e1713 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1353,19 +1353,18 @@ object Types {
def tp1: Type
def tp2: Type
def isAnd: Boolean
- def derivedAndOrType(tp1: Type, tp2: Type)(implicit ctx: Context): AndOrType // needed?
-
+ def derivedAndOrType(tp1: Type, tp2: Type)(implicit ctx: Context): Type // needed?
}
abstract case class AndType(tp1: Type, tp2: Type) extends CachedGroundType with AndOrType {
def isAnd = true
- def derivedAndType(tp1: Type, tp2: Type)(implicit ctx: Context): AndType =
+ def derivedAndType(tp1: Type, tp2: Type)(implicit ctx: Context): Type =
if ((tp1 eq this.tp1) && (tp2 eq this.tp2)) this
- else AndType(tp1, tp2)
+ else AndType.make(tp1, tp2)
- def derivedAndOrType(tp1: Type, tp2: Type)(implicit ctx: Context): AndOrType =
+ def derivedAndOrType(tp1: Type, tp2: Type)(implicit ctx: Context): Type =
derivedAndType(tp1, tp2)
override def computeHash = doHash(tp1, tp2)
@@ -1381,18 +1380,19 @@ object Types {
def unchecked(tp1: Type, tp2: Type)(implicit ctx: Context) = {
unique(new CachedAndType(tp1, tp2))
}
+ def make(tp1: Type, tp2: Type)(implicit ctx: Context): Type =
+ if (tp1 eq tp2) tp1 else apply(tp1, tp2)
}
abstract case class OrType(tp1: Type, tp2: Type) extends CachedGroundType with AndOrType {
assert(tp1.isInstanceOf[ValueType] && tp2.isInstanceOf[ValueType])
-
def isAnd = false
- def derivedOrType(tp1: Type, tp2: Type)(implicit ctx: Context): OrType =
+ def derivedOrType(tp1: Type, tp2: Type)(implicit ctx: Context): Type =
if ((tp1 eq this.tp1) && (tp2 eq this.tp2)) this
- else OrType(tp1, tp2)
+ else OrType.make(tp1, tp2)
- def derivedAndOrType(tp1: Type, tp2: Type)(implicit ctx: Context): AndOrType =
+ def derivedAndOrType(tp1: Type, tp2: Type)(implicit ctx: Context): Type =
derivedOrType(tp1, tp2)
override def computeHash = doHash(tp1, tp2)
@@ -1403,6 +1403,8 @@ object Types {
object OrType {
def apply(tp1: Type, tp2: Type)(implicit ctx: Context) =
unique(new CachedOrType(tp1, tp2))
+ def make(tp1: Type, tp2: Type)(implicit ctx: Context): Type =
+ if (tp1 eq tp2) tp1 else apply(tp1, tp2)
}
// ----- Method types: MethodType/ExprType/PolyType -------------------------------