aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-08-30 11:10:37 +0200
committerMartin Odersky <odersky@gmail.com>2013-08-30 11:10:37 +0200
commit860fd2eb286c48d36655ad99a068a2e61bdb1381 (patch)
tree0c75f7aa2228adae973a16ec5b5afccaaa7c68be /src/dotty/tools
parent28f8102d1b4e8c8fd2d2f1838b49e70844245a5f (diff)
downloaddotty-860fd2eb286c48d36655ad99a068a2e61bdb1381.tar.gz
dotty-860fd2eb286c48d36655ad99a068a2e61bdb1381.tar.bz2
dotty-860fd2eb286c48d36655ad99a068a2e61bdb1381.zip
More tests and fixes related to inference.
Main blooper: TypeVars got dereferenced in all Typemaps, so disappeared too quickly from types during inference.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala10
-rw-r--r--src/dotty/tools/dotc/core/TyperState.scala10
-rw-r--r--src/dotty/tools/dotc/core/Types.scala45
-rw-r--r--src/dotty/tools/dotc/printing/PlainPrinter.scala5
-rw-r--r--src/dotty/tools/dotc/typer/ErrorReporting.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala17
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala2
7 files changed, 55 insertions, 36 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index b7ae92b46..bdfe21561 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -60,6 +60,7 @@ class TypeComparer(implicit val ctx: Context) extends DotClass {
val bounds = constraint(param).asInstanceOf[TypeBounds]
val bound = if (fromBelow) bounds.lo else bounds.hi
val inst = removeParam(bound)
+ println(s"approx ${param.show}, from below = $fromBelow, bound = ${bound.show}, inst = ${inst.show}")
constraint = constraint.replace(param, inst)
inst
}
@@ -130,7 +131,7 @@ class TypeComparer(implicit val ctx: Context) extends DotClass {
case _ => secondTry(tp1, tp2)
}
case tp2: TypeVar =>
- firstTry(tp1, tp2.thisInstance)
+ firstTry(tp1, tp2.underlying)
case tp2: WildcardType =>
tp2.optBounds match {
case TypeBounds(_, hi) => isSubType(tp1, hi)
@@ -152,7 +153,7 @@ class TypeComparer(implicit val ctx: Context) extends DotClass {
case _ => thirdTry(tp1, tp2)
}
case tp1: TypeVar =>
- secondTry(tp1.thisInstance, tp2)
+ secondTry(tp1.underlying, tp2)
case tp1: WildcardType =>
tp1.optBounds match {
case TypeBounds(lo, _) => isSubType(lo, tp2)
@@ -168,8 +169,9 @@ class TypeComparer(implicit val ctx: Context) extends DotClass {
def thirdTryNamed(tp1: Type, tp2: NamedType): Boolean = tp2.info match {
case TypeBounds(lo2, hi2) =>
- isSubType(tp1, lo2) ||
- (tp2.symbol is GADTFlexType) && trySetType(tp2, TypeBounds(lo2 | tp1, hi2))
+ (isSubType(tp1, lo2)
+ || (tp2.symbol is GADTFlexType) && trySetType(tp2, TypeBounds(lo2 | tp1, hi2))
+ || fourthTry(tp1, tp2))
case _ =>
val cls2 = tp2.symbol
(cls2 == defn.SingletonClass && tp1.isStable
diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala
index b00e55e29..7f161d994 100644
--- a/src/dotty/tools/dotc/core/TyperState.scala
+++ b/src/dotty/tools/dotc/core/TyperState.scala
@@ -18,7 +18,7 @@ class TyperState(val reporter: Reporter = ThrowingReporter) extends DotClass {
/** A map that records for instantiated type vars their instance type.
* Used only in a temporary way for contexts that may be retracted
- * without also retracting the type var.
+ * without also retracting the type var.
*/
def instType: SimpleMap[TypeVar, Type] = SimpleMap.Empty
@@ -34,6 +34,9 @@ class TyperState(val reporter: Reporter = ThrowingReporter) extends DotClass {
class MutableTyperState(previous: TyperState, reporter: Reporter)
extends TyperState(reporter) {
+ def checkConsistent() =
+ for (tvar <- undetVars) assert(constraint(tvar.origin) != NoType, tvar)
+
private var myConstraint: Constraint = previous.constraint
private var myUndetVars: Set[TypeVar] = previous.undetVars
private var myInstType: SimpleMap[TypeVar, Type] = previous.instType
@@ -43,7 +46,10 @@ extends TyperState(reporter) {
override def instType = myInstType
override def constraint_=(c: Constraint) = myConstraint = c
- override def undetVars_=(vs: Set[TypeVar]) = myUndetVars = vs
+ override def undetVars_=(vs: Set[TypeVar]) = {
+ myUndetVars = vs
+ //checkConsistent()
+ }
override def instType_=(m: SimpleMap[TypeVar, Type]): Unit = myInstType = m
override def fresh: TyperState = new MutableTyperState(this, new StoreReporter)
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index fc2592b46..19c0e3128 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -117,7 +117,7 @@ object Types {
classSymbol is ModuleClass
/** Is this type produced as a repair for an error? */
- final def isError(implicit ctx: Context): Boolean = thisInstance match {
+ final def isError(implicit ctx: Context): Boolean = stripTypeVar match {
case ErrorType => true
case tp => (tp.typeSymbol is Erroneous) || (tp.termSymbol is Erroneous)
}
@@ -144,7 +144,7 @@ object Types {
ctx.isVolatile(this)
/** Does the type carry an annotation that is an instance of `cls`? */
- final def hasAnnotation(cls: ClassSymbol)(implicit ctx: Context): Boolean = thisInstance match {
+ final def hasAnnotation(cls: ClassSymbol)(implicit ctx: Context): Boolean = stripTypeVar match {
case AnnotatedType(annot, tp) => annot.symbol == cls || tp.hasAnnotation(cls)
case _ => false
}
@@ -177,15 +177,15 @@ object Types {
final def foreach(f: Type => Unit): Unit = ???
/** Map function over elements of an AndType, rebuilding with & */
- def mapAnd(f: Type => Type)(implicit ctx: Context): Type = thisInstance match {
+ def mapAnd(f: Type => Type)(implicit ctx: Context): Type = stripTypeVar match {
case AndType(tp1, tp2) => tp1.mapAnd(f) & tp2.mapAnd(f)
- case tp => f(tp)
+ case _ => f(this)
}
/** Map function over elements of an OrType, rebuilding with | */
- final def mapOr(f: Type => Type)(implicit ctx: Context): Type = thisInstance match {
+ final def mapOr(f: Type => Type)(implicit ctx: Context): Type = stripTypeVar match {
case OrType(tp1, tp2) => tp1.mapOr(f) | tp2.mapOr(f)
- case tp => f(tp)
+ case _ => f(this)
}
// ----- Associated symbols ----------------------------------------------
@@ -514,7 +514,7 @@ object Types {
/** Map a TypeVar to either its instance if it is instantiated, or its origin,
* if not. Identity on all other types.
*/
- def thisInstance(implicit ctx: Context): Type = this
+ def stripTypeVar(implicit ctx: Context): Type = this
/** Widen from singleton type to its underlying non-singleton
* base type by applying one or more `underlying` dereferences,
@@ -535,9 +535,9 @@ object Types {
}
/** If this is an alias type, its alias, otherwise the type itself */
- final def dealias(implicit ctx: Context): Type = thisInstance match {
+ final def dealias(implicit ctx: Context): Type = stripTypeVar match {
case tp: TypeRef if tp.symbol.isAliasType => tp.info.bounds.hi
- case tp => tp
+ case _ => this
}
/** Widen from constant type to its underlying non-constant
@@ -551,9 +551,9 @@ object Types {
/** If this is a refinement type, the unrefined parent,
* else the type itself.
*/
- final def unrefine(implicit ctx: Context): Type = thisInstance match {
+ final def unrefine(implicit ctx: Context): Type = stripTypeVar match {
case tp @ RefinedType(tycon, _) => tycon.unrefine
- case tp => tp
+ case _ => this
}
/** Map references to Object to references to Any; needed for Java interop */
@@ -801,7 +801,7 @@ object Types {
*/
final def typeArgs(implicit ctx: Context): List[Type] = {
var tparams: List[TypeSymbol] = null
- def recur(tp: Type, refineCount: Int): mutable.ListBuffer[Type] = tp match {
+ def recur(tp: Type, refineCount: Int): mutable.ListBuffer[Type] = tp.stripTypeVar match {
case tp @ RefinedType(tycon, name) =>
val buf = recur(tycon, refineCount + 1)
if (buf == null) null
@@ -817,7 +817,7 @@ object Types {
if (refineCount == 0) null
else new mutable.ListBuffer[Type]
}
- val buf = recur(thisInstance, 0)
+ val buf = recur(this, 0)
if (buf == null) Nil else buf.toList
}
@@ -840,7 +840,7 @@ object Types {
* Otherwise return 0 and the type itself
*/
final def splitArray(implicit ctx: Context): (Int, Type) = {
- def recur(n: Int, tp: Type): (Int, Type) = tp match {
+ def recur(n: Int, tp: Type): (Int, Type) = tp.stripTypeVar match {
case RefinedType(tycon, _) if tycon.isArray =>
tp.typeArgs match {
case arg :: Nil => recur(n + 1, arg)
@@ -849,7 +849,7 @@ object Types {
case _ =>
(n, tp)
}
- recur(0, thisInstance)
+ recur(0, this)
}
/** Given a type alias
@@ -1759,7 +1759,7 @@ object Types {
* is also a singleton type.
*/
def instantiate(fromBelow: Boolean)(implicit ctx: Context): Type = {
- def upperBound = ctx.typerState.constraint(origin).bounds.hi
+ val upperBound = ctx.typerState.constraint(origin).bounds.hi
def isSingleton(tp: Type): Boolean = tp match {
case tp: SingletonType => true
case AndType(tp1, tp2) => isSingleton(tp1) | isSingleton(tp2)
@@ -1773,13 +1773,13 @@ object Types {
}
/** If the variable is instantiated, its instance, otherwise its origin */
- override def thisInstance(implicit ctx: Context) = {
+ override def stripTypeVar(implicit ctx: Context) = {
val inst = instanceOpt
if (inst.exists) inst else origin
}
- /** Same as `thisInstance` */
- override def underlying(implicit ctx: Context): Type = thisInstance
+ /** Same as `stripTypeVar` */
+ override def underlying(implicit ctx: Context): Type = stripTypeVar
override def hashCode: Int = System.identityHashCode(this)
override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
@@ -2027,7 +2027,7 @@ object Types {
case tp: RefinedType =>
isInstantiatable(tp.underlying)
case tp: TypeVar =>
- isInstantiatable(tp.thisInstance)
+ isInstantiatable(tp.underlying)
case _ =>
false
}
@@ -2088,7 +2088,8 @@ object Types {
tp.derivedAnnotatedType(mapOver(annot), this(underlying))
case tp: TypeVar =>
- apply(tp.thisInstance)
+ val inst = tp.instanceOpt
+ if (inst.exists) apply(inst) else tp
case tp @ WildcardType =>
tp.derivedWildcardType(mapOver(tp.optBounds))
@@ -2192,7 +2193,7 @@ object Types {
this(this(x, annot), underlying)
case tp: TypeVar =>
- foldOver(x, tp.thisInstance)
+ foldOver(x, tp.underlying)
case tp: WildcardType =>
foldOver(x, tp.optBounds)
diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala
index b4e2e3770..f86075d83 100644
--- a/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -125,7 +125,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
case tp: ExprType =>
changePrec(GlobalPrec) { "=> " ~ toText(tp.resultType) }
case tp: PolyType =>
- def paramText(name: TypeName, bounds: TypeBounds) = toText(polyParamName(name)) ~ ": " ~ toText(bounds)
+ def paramText(name: TypeName, bounds: TypeBounds) =
+ toText(polyParamName(name)) ~ toText(bounds)
changePrec(GlobalPrec) {
"[" ~
Text((tp.paramNames, tp.paramBounds).zipped map paramText, ", ") ~
@@ -136,7 +137,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
case AnnotatedType(annot, tpe) =>
toTextLocal(tpe) ~ " " ~ toText(annot)
case tp: TypeVar =>
- toTextLocal(tp.underlying)
+ toTextLocal(tp.underlying) ~ "'" // debug for now, so that we can see where the TypeVars are.
case _ =>
tp.fallbackToText(this)
}
diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala
index 177882688..cda37f486 100644
--- a/src/dotty/tools/dotc/typer/ErrorReporting.scala
+++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala
@@ -93,7 +93,7 @@ object ErrorReporting {
def treatArg(arg: Any, suffix: String): (Any, String) = arg match {
case arg: Showable =>
(arg.show, suffix)
- case arg: List[_] if suffix.head == '%' =>
+ case arg: List[_] if suffix.nonEmpty && suffix.head == '%' =>
val (sep, rest) = suffix.tail.span(_ != '%')
if (rest.nonEmpty) (arg mkString sep, rest.tail)
else (arg, suffix)
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 06b6e1487..1083b4f2e 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -124,6 +124,7 @@ object Inferencing {
false
case tvar: TypeVar if forceIt && !tvar.isInstantiated =>
val inst = tvar.instantiate(fromBelow = true)
+ println(i"forced instantiation of ${tvar.origin} = $inst")
inst != defn.NothingType && inst != defn.NullType
case _ =>
true
@@ -193,10 +194,18 @@ object Inferencing {
val vs = tp.variances(tvar =>
(ctx.typerState.undetVars contains tvar) && (pos contains tvar.pos))
for ((tvar, v) <- vs)
- if (v == 1) tvar.instantiate(fromBelow = true)
- else if (v == -1) tvar.instantiate(fromBelow = false)
- for (tvar <- ctx.typerState.undetVars if !(vs contains tvar))
- tvar.instantiate(fromBelow = false)
+ if (v == 1) {
+ println(i"interpolate covariant $tvar in $tp")
+ tvar.instantiate(fromBelow = true)
+ }
+ else if (v == -1) {
+ println(i"interpolate contrvariant $tvar in $tp")
+ tvar.instantiate(fromBelow = false)
+ }
+ for (tvar <- ctx.typerState.undetVars if (pos contains tvar.pos) && !(vs contains tvar)) {
+ println(i"interpolate non-occurring $tvar in $tp")
+ tvar.instantiate(fromBelow = true)
+ }
}
/** Instantiate undetermined type variables to that type `tp` is
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 97cc37cc3..265326480 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -339,7 +339,7 @@ class Namer { typer: Typer =>
}
/** Typecheck tree during completion, and remember result in typedtree map */
- private def typedAheadImpl(tree: Tree, pt: Type)(implicit ctx: Context): tpd.Tree =
+ private def typedAheadImpl(tree: Tree, pt: Type)(implicit ctx: Context): tpd.Tree =
typedTree.getOrElseUpdate(expanded(tree), typer.typedUnadapted(tree, pt))
def typedAheadType(tree: Tree, pt: Type = WildcardType)(implicit ctx: Context): tpd.Tree =