aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-10-10 18:38:41 +0200
committerMartin Odersky <odersky@gmail.com>2013-10-10 18:38:41 +0200
commitb4c0e4af5ef03384f24e370059724be7c1ca6fb3 (patch)
tree8079557288014aa1e5c9815e83189491dc9415e8 /src/dotty/tools/dotc
parent7ebb48127be6c02578596d0b9e627af250d11863 (diff)
downloaddotty-b4c0e4af5ef03384f24e370059724be7c1ca6fb3.tar.gz
dotty-b4c0e4af5ef03384f24e370059724be7c1ca6fb3.tar.bz2
dotty-b4c0e4af5ef03384f24e370059724be7c1ca6fb3.zip
Fixed missing type comparisons for bound types.
Also, new method "explained" in TypeComparers.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala40
-rw-r--r--src/dotty/tools/dotc/core/Types.scala10
-rw-r--r--src/dotty/tools/dotc/typer/ErrorReporting.scala10
3 files changed, 46 insertions, 14 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 46eabb606..5701fcc95 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -105,6 +105,13 @@ class TypeComparer(initctx: Context) extends DotClass {
val cs = constraint
try {
recCount += 1
+/* !!! DEBUG
+ if (isWatched(tp1) && isWatched(tp2) && !(this.isInstanceOf[ExplainingTypeComparer])) {
+ val explained = new ExplainingTypeComparer(ctx)
+ println("***** watched:")
+ println(TypeComparer.explained(_.typeComparer.isSubType(tp1, tp2)))
+ }
+*/
val result =
if (recCount < LogPendingSubTypesThreshold) firstTry(tp1, tp2)
else monitoredIsSubType(tp1, tp2)
@@ -159,11 +166,15 @@ class TypeComparer(initctx: Context) extends DotClass {
secondTry(tp1, tp2)
}
case tp2: PolyParam =>
- //println(constraint.show)
- constraint(tp2) match {
- case TypeBounds(lo, _) => isSubType(tp1, lo) || addConstraint(tp2, TypeBounds.lower(tp1.widen))
- case _ => secondTry(tp1, tp2)
+ tp2 == tp1 || {
+ //println(constraint.show)
+ constraint(tp2) match {
+ case TypeBounds(lo, _) => isSubType(tp1, lo) || addConstraint(tp2, TypeBounds.lower(tp1.widen))
+ case _ => secondTry(tp1, tp2)
+ }
}
+ case tp2: BoundType =>
+ tp2 == tp1 || secondTry(tp1, tp2)
case tp2: TypeVar =>
isSubType(tp1, tp2.underlying)
case tp2: ProtoType =>
@@ -184,10 +195,14 @@ class TypeComparer(initctx: Context) extends DotClass {
def secondTry(tp1: Type, tp2: Type): Boolean = tp1 match {
case tp1: PolyParam =>
- constraint(tp1) match {
- case TypeBounds(_, hi) => isSubType(hi, tp2) || addConstraint(tp1, TypeBounds.upper(tp2))
- case _ => thirdTry(tp1, tp2)
+ (tp1 == tp2) || {
+ constraint(tp1) match {
+ case TypeBounds(_, hi) => isSubType(hi, tp2) || addConstraint(tp1, TypeBounds.upper(tp2))
+ case _ => thirdTry(tp1, tp2)
+ }
}
+ case tp1: BoundType =>
+ tp1 == tp2 || secondTry(tp1, tp2)
case tp1: TypeVar =>
isSubType(tp1.underlying, tp2)
case tp1: WildcardType =>
@@ -681,6 +696,7 @@ class TypeComparer(initctx: Context) extends DotClass {
* Issue a warning and return the winner.
*/
private def andConflict(tp1: Type, tp2: Type): Type = {
+ // println(disambiguated(implicit ctx => TypeComparer.explained(_.typeComparer.isSubType(tp1, tp2)))) !!!DEBUG
val winner = if (isAsGood(tp2, tp1) && !isAsGood(tp1, tp2)) tp2 else tp1
def msg = disambiguated { implicit ctx =>
s"${mergeErrorMsg(tp1, tp2)} as members of one type; keeping only ${showType(winner)}"
@@ -753,6 +769,14 @@ class TypeComparer(initctx: Context) extends DotClass {
def copyIn(ctx: Context) = new TypeComparer(ctx)
}
+object TypeComparer {
+ def explained[T](op: Context => T)(implicit ctx: Context): String = {
+ val nestedCtx = ctx.fresh.withTypeComparerFn(new ExplainingTypeComparer(_))
+ op(nestedCtx)
+ nestedCtx.typeComparer.toString
+ }
+}
+
class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
private var indent = 0
private val b = new StringBuilder
@@ -772,7 +796,7 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
}
override def isSubType(tp1: Type, tp2: Type) =
- traceIndented(s"${show(tp1)} <:< ${show(tp2)}") {
+ traceIndented(s"${show(tp1)} <:< ${show(tp2)} ${tp1.getClass} ${tp2.getClass}") {
super.isSubType(tp1, tp2)
}
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index b5cd8c3ee..257128821 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2058,9 +2058,11 @@ object Types {
final class CachedTypeBounds(lo: Type, hi: Type) extends TypeBounds(lo, hi)
final class CoTypeBounds(lo: Type, hi: Type) extends TypeBounds(lo, hi) {
override def variance = 1
+ override def toString = "Co" + super.toString
}
final class ContraTypeBounds(lo: Type, hi: Type) extends TypeBounds(lo, hi) {
override def variance = -1
+ override def toString = "Contra" + super.toString
}
object TypeBounds {
@@ -2412,4 +2414,12 @@ object Types {
// ----- Debug ---------------------------------------------------------
var debugTrace = false
+
+ val watchList = List[String](
+ ) map (_.toTypeName)
+
+ def isWatched(tp: Type) = tp match {
+ case TypeRef(_, name) => watchList contains name
+ case _ => false
+ }
}
diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala
index 16f994e90..9b6188fe6 100644
--- a/src/dotty/tools/dotc/typer/ErrorReporting.scala
+++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala
@@ -70,12 +70,10 @@ object ErrorReporting {
def typeMismatchStr(found: Type, expected: Type) = disambiguated { implicit ctx =>
val (typerStateStr, explanationStr) =
- if (ctx.settings.explaintypes.value) {
- val nestedCtx = ctx.fresh.withTypeComparerFn(new ExplainingTypeComparer(_))
- (found <:< expected)(nestedCtx)
- ("\n" + ctx.typerState.show, "\n" + nestedCtx.typeComparer.toString)
- }
- else ("", "")
+ if (ctx.settings.explaintypes.value)
+ ("\n" + ctx.typerState.show, "\n" + TypeComparer.explained((found <:< expected)(_)))
+ else
+ ("", "")
i"""type mismatch:
| found : $found
| required: $expected""".stripMargin + typerStateStr + explanationStr