aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeComparer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-09-30 10:07:41 +0200
committerMartin Odersky <odersky@gmail.com>2013-09-30 10:11:55 +0200
commite28dd856f6c0ccbd4094a73311a9c820f73913c4 (patch)
tree31acfaf5d391cb37db486c4bd585520bb228c165 /src/dotty/tools/dotc/core/TypeComparer.scala
parent968b608ea6f2d42d48f30e311d6008600dad27a8 (diff)
downloaddotty-e28dd856f6c0ccbd4094a73311a9c820f73913c4.tar.gz
dotty-e28dd856f6c0ccbd4094a73311a9c820f73913c4.tar.bz2
dotty-e28dd856f6c0ccbd4094a73311a9c820f73913c4.zip
Changed logic for merges in lub/glb
Now throws an exception for merge conflicts of types joint by |, a warning for types joint by &. Exception is handled as in the case of CyclicRefernce. Also: Added several typerState.checkConsistent for future debugging purposes.
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeComparer.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala37
1 files changed, 29 insertions, 8 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 1d853c44d..13b900e18 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -3,6 +3,7 @@ package dotc
package core
import Types._, Contexts._, Symbols._, Flags._
+import Decorators.sourcePos
import StdNames.nme
import collection.mutable
import util.SimpleMap
@@ -159,7 +160,7 @@ class TypeComparer(initctx: Context) extends DotClass {
case tp2: PolyParam =>
//println(constraint.show)
constraint(tp2) match {
- case TypeBounds(lo, _) => isSubType(tp1, lo) || addConstraint(tp2, TypeBounds.lower(tp1))
+ case TypeBounds(lo, _) => isSubType(tp1, lo) || addConstraint(tp2, TypeBounds.lower(tp1.widen))
case _ => secondTry(tp1, tp2)
}
case tp2: TypeVar =>
@@ -409,6 +410,8 @@ class TypeComparer(initctx: Context) extends DotClass {
else tp2 match { // normalize to disjunctive normal form if possible.
case OrType(tp21, tp22) =>
tp1 & tp21 | tp1 & tp22
+// case tp2: PolyType =>
+// mergePoly(tp2, tp1, lower = true)
case _ =>
tp1 match {
case OrType(tp11, tp12) =>
@@ -426,11 +429,11 @@ class TypeComparer(initctx: Context) extends DotClass {
case tp2: TypeBounds =>
return TypeBounds(tp1.lo | tp2.lo, tp1.hi & tp2.hi)
case tp2: ClassInfo =>
- return classMerge(tp2, tp1)
+ return classMerge(tp2, tp1, isAnd = true)
case _ =>
}
case tp1: ClassInfo =>
- return classMerge(tp1, tp2)
+ return classMerge(tp1, tp2, isAnd = true)
case _ =>
}
AndType(tp1, tp2)
@@ -459,11 +462,11 @@ class TypeComparer(initctx: Context) extends DotClass {
case tp2: TypeBounds =>
return TypeBounds(tp1.lo & tp2.lo, tp1.hi | tp2.hi)
case tp2: ClassInfo =>
- return classMerge(tp2, tp1)
+ return classMerge(tp2, tp1, isAnd = false)
case _ =>
}
case tp1: ClassInfo =>
- return classMerge(tp1, tp2)
+ return classMerge(tp1, tp2, isAnd = false)
case _ =>
}
OrType(tp1, tp2)
@@ -529,9 +532,27 @@ class TypeComparer(initctx: Context) extends DotClass {
* can also be arbitrarily instantiated. In both cases we need to
* make sure that such types do not actually arise in source programs.
*/
- private def classMerge(cinfo: ClassInfo, tp2: Type)(implicit ctx: Context): Type = tp2 match {
- case cinfo2: ClassInfo if isAsGood(cinfo2, cinfo) && !isAsGood(cinfo, cinfo2) => cinfo2
- case _ => cinfo
+ private def classMerge(cinfo: ClassInfo, tp2: Type, isAnd: Boolean)(implicit ctx: Context): Type = {
+
+ def showTypeType(tp: Type)(implicit ctx: Context) = tp match {
+ case ClassInfo(_, cls, _, _, _) => cls.showLocated
+ case bounds: TypeBounds => "type bounds" + bounds.show
+ case _ => tp.show
+ }
+
+ def msg = s"cannot merge ${showTypeType(cinfo)} with ${showTypeType(tp2)}"
+ val pos = ctx.tree.pos
+
+ if (isAnd) {
+ val winner = tp2 match {
+ case cinfo2: ClassInfo if isAsGood(cinfo2, cinfo) && !isAsGood(cinfo, cinfo2) => cinfo2
+ case _ => cinfo
+ }
+ ctx.warning(s"$msg as members of one type; keeping only ${showTypeType(winner)}", ctx.tree.pos)
+ winner
+ }
+ else
+ throw new ClassMergeError(msg)
}
private def isAsGood(cinfo1: ClassInfo, cinfo2: ClassInfo)(implicit ctx: Context): Boolean =