From 28e9bb7c3f551265c7de671cc9eccc39bd2697de Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 14 Feb 2014 13:49:57 +0100 Subject: 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. --- src/dotty/tools/dotc/core/TypeComparer.scala | 2 +- src/dotty/tools/dotc/core/Types.scala | 20 +++++++++++--------- 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 ------------------------------- -- cgit v1.2.3