aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Types.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-10-01 21:35:58 +0200
committerGuillaume Martres <smarter@ubuntu.com>2016-10-11 19:21:02 +0200
commit98a69d90b16f0cc997255f097d3d5d9f2a60301b (patch)
treec3640fb82f53f4f6e250de59d3536f638b63f1aa /src/dotty/tools/dotc/core/Types.scala
parentf6291e42082708e164ebc3456d84e69f4f29cf59 (diff)
downloaddotty-98a69d90b16f0cc997255f097d3d5d9f2a60301b.tar.gz
dotty-98a69d90b16f0cc997255f097d3d5d9f2a60301b.tar.bz2
dotty-98a69d90b16f0cc997255f097d3d5d9f2a60301b.zip
Keep or types
Don't replace them by their dominators, unless one of the following holds: - language:Scala2 mode is on - we are at the point of findMember selection - we compare with a higher-kinded application This means approximateUnion is now split into harmonizeUnion and orDominator which each implement one of the former's two functionalities.
Diffstat (limited to 'src/dotty/tools/dotc/core/Types.scala')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala46
1 files changed, 21 insertions, 25 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 2f1b6b829..0f81f8c38 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -436,8 +436,12 @@ object Types {
tp.cls.findMember(name, pre, excluded)
case AndType(l, r) =>
goAnd(l, r)
- case OrType(l, r) =>
- goOr(l, r)
+ case tp: OrType =>
+ // we need to keep the invariant that `pre <: tp`. Branch `union-types-narrow-prefix`
+ // achieved that by narrowing `pre` to each alternative, but it led to merge errors in
+ // lots of places. The present strategy is instead of widen `tp` using `join` to be a
+ // supertype of `pre`.
+ go(tp.join)
case tp: JavaArrayType =>
defn.ObjectType.findMember(name, pre, excluded)
case ErrorType =>
@@ -556,7 +560,6 @@ object Types {
def goAnd(l: Type, r: Type) = {
go(l) & (go(r), pre, safeIntersection = ctx.pendingMemberSearches.contains(name))
}
- def goOr(l: Type, r: Type) = go(l) | (go(r), pre)
{ val recCount = ctx.findMemberCount + 1
ctx.findMemberCount = recCount
@@ -1230,28 +1233,6 @@ object Types {
*/
def simplified(implicit ctx: Context) = ctx.simplify(this, null)
- /** Approximations of union types: We replace a union type Tn | ... | Tn
- * by the smallest intersection type of baseclass instances of T1,...,Tn.
- * Example: Given
- *
- * trait C[+T]
- * trait D
- * class A extends C[A] with D
- * class B extends C[B] with D with E
- *
- * we approximate `A | B` by `C[A | B] with D`
- *
- * As a second measure we also homogenize refinements containing
- * type variables. For instance, if `A` is an instantiatable type variable,
- * then
- *
- * ArrayBuffer[Int] | ArrayBuffer[A]
- *
- * is approximated by instantiating `A` to `Int` and returning `ArrayBuffer[Int]`
- * instead of `ArrayBuffer[_ >: Int | A <: Int & A]`
- */
- def approximateUnion(implicit ctx: Context) = ctx.approximateUnion(this)
-
/** customized hash code of this type.
* NotCached for uncached types. Cached types
* compute hash and use it as the type's hashCode.
@@ -2233,9 +2214,24 @@ object Types {
}
abstract case class OrType(tp1: Type, tp2: Type) extends CachedGroundType with AndOrType {
+
assert(tp1.isInstanceOf[ValueType] && tp2.isInstanceOf[ValueType])
def isAnd = false
+ private[this] var myJoin: Type = _
+ private[this] var myJoinPeriod: Period = Nowhere
+
+ /** Replace or type by the closest non-or type above it */
+ def join(implicit ctx: Context): Type = {
+ if (myJoinPeriod != ctx.period) {
+ myJoin = ctx.orDominator(this)
+ core.println(i"join of $this == $myJoin")
+ assert(myJoin != this)
+ myJoinPeriod = ctx.period
+ }
+ myJoin
+ }
+
def derivedOrType(tp1: Type, tp2: Type)(implicit ctx: Context): Type =
if ((tp1 eq this.tp1) && (tp2 eq this.tp2)) this
else OrType.make(tp1, tp2)