summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2008-08-01 18:31:47 +0000
committerMartin Odersky <odersky@gmail.com>2008-08-01 18:31:47 +0000
commit60963bf600b282a1978aed96cbb5edcdba6c1709 (patch)
treed25b3f7077fbe33d6375a75ba4397820ea1bf4c7
parentf39f93c4730993537c7e08c7a7752ea5ccef9de5 (diff)
downloadscala-60963bf600b282a1978aed96cbb5edcdba6c1709.tar.gz
scala-60963bf600b282a1978aed96cbb5edcdba6c1709.tar.bz2
scala-60963bf600b282a1978aed96cbb5edcdba6c1709.zip
Fixed #1049 and #1062
-rwxr-xr-xsrc/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala33
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala91
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala12
4 files changed, 78 insertions, 73 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
index c1c251c9bd..f7b3d77d41 100755
--- a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
+++ b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
@@ -5,7 +5,7 @@
package scala.tools.nsc.symtab
import scala.collection.mutable.ListBuffer
-import util.BitSet
+import Math.max
/** A base type sequence (BaseTypeSeq) is an ordered sequence spanning all the base types
* of a type. It characterized by the following two laws:
@@ -23,7 +23,7 @@ import util.BitSet
* to avoid confusion with function closures.
*/
trait BaseTypeSeqs {
- self: SymbolTable =>
+ this: SymbolTable =>
import definitions._
class BaseTypeSeq(parents: List[Type], elems: Array[Type]) {
@@ -42,7 +42,7 @@ trait BaseTypeSeqs {
//Console.println("compute closure of "+this+" => glb("+variants+")")
elems(i) = NoType
try {
- mergePrefixAndArgs(variants, -1, maxBaseTypeSeqDepth(variants) + LubGlbMargin) match {
+ mergePrefixAndArgs(variants, -1, lubDepth(variants)) match {
case Some(tp0) =>
elems(i) = tp0
tp0
@@ -126,7 +126,32 @@ trait BaseTypeSeqs {
*/
lazy val maxDepth: Int = {
var d = 0
- for (i <- 0 until length) d = Math.max(d, self.maxDepth(elems(i)))
+ for (i <- 0 until length) d = Math.max(d, maxDpth(elems(i)))
+ d
+ }
+
+ /** The maximum depth of type `tp' */
+ private def maxDpth(tp: Type): Int = tp match {
+ case TypeRef(pre, sym, args) =>
+ max(maxDpth(pre), maxDpth(args) + 1)
+ case RefinedType(parents, decls) =>
+ max(maxDpth(parents), maxDpth(decls.toList.map(_.info)) + 1)
+ case TypeBounds(lo, hi) =>
+ max(maxDpth(lo), maxDpth(hi))
+ case MethodType(paramtypes, result) =>
+ maxDpth(result)
+ case PolyType(tparams, result) =>
+ max(maxDpth(result), maxDpth(tparams map (_.info)) + 1)
+ case ExistentialType(tparams, result) =>
+ max(maxDpth(result), maxDpth(tparams map (_.info)) + 1)
+ case _ =>
+ 1
+ }
+
+ /** The maximum depth of all types `tps' */
+ private def maxDpth(tps: Seq[Type]): Int = {
+ var d = 0
+ for (tp <- tps) d = max(d, maxDpth(tp))
d
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 87c60d3781..fe36c0a3b4 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -78,7 +78,6 @@ trait Types {
private var explainSwitch = false
private var checkMalformedSwitch = false // todo: it's now always false. Remove all code that depends on this switch.
- final val LubGlbMargin = 0
private final val LogPendingSubTypesThreshold = 50
private final val LogPendingBaseTypesThreshold = 50
@@ -88,6 +87,8 @@ trait Types {
/** Decrement depth unless it is a don't care */
private final def decr(depth: Int) = if (depth == AnyDepth) AnyDepth else depth - 1
+ private final val printLubs = false
+
/** The current skolemization level, needed for the algorithms
* in isSameType, isSubType that do constraint solving under a prefix
*/
@@ -3168,44 +3169,22 @@ A type's typeSymbol should never be inspected directly.
// Helper Methods -------------------------------------------------------------
- import Math.max
-
private var nextid = 0
private def freshName() = {
nextid += 1
"_"+nextid
}
- /** The maximum depth of all types in the base type sequences of each of the types `tps' */
- final def maxBaseTypeSeqDepth(tps: Seq[Type]): Int = {
- var d = 0
- for (tp <- tps) d = max(d, tp.baseTypeSeqDepth)
- d
- }
+ final val LubGlbMargin = 0
- /** The maximum depth of all types `tps' */
- final def maxDepth(tps: Seq[Type]): Int = {
+ /** The maximum allowable depth of lubs or glbs over types `ts'
+ * This is the maximum depth of all types in the base type sequences
+ * of each of the types `ts', plus LubGlbMargin
+ */
+ def lubDepth(ts: List[Type]) = {
var d = 0
- for (tp <- tps) d = max(d, maxDepth(tp))
- d
- }
-
- /** The maximum depth of type `tp' */
- final def maxDepth(tp: Type): Int = tp match {
- case TypeRef(pre, sym, args) =>
- max(maxDepth(pre), maxDepth(args) + 1)
- case RefinedType(parents, decls) =>
- max(maxDepth(parents), maxDepth(decls.toList.map(_.info)) + 1)
- case TypeBounds(lo, hi) =>
- max(maxDepth(lo), maxDepth(hi))
- case MethodType(paramtypes, result) =>
- maxDepth(result)
- case PolyType(tparams, result) =>
- max(maxDepth(result), maxDepth(tparams map (_.info)) + 1)
- case ExistentialType(tparams, result) =>
- max(maxDepth(result), maxDepth(tparams map (_.info)) + 1)
- case _ =>
- 1
+ for (tp <- ts) d = Math.max(d, tp.baseTypeSeqDepth)
+ d + LubGlbMargin
}
final def isValid(period: Period): Boolean =
@@ -3634,16 +3613,8 @@ A type's typeSymbol should never be inspected directly.
} finally {
skolemizationLevel -= 1
}
- case (RefinedType(parents1, ref1), _: ExistentialType)
- if (parents1 exists (_.isInstanceOf[ExistentialType])) =>
- try {
- skolemizationLevel += 1
- RefinedType(parents1 map (_.skolemizeExistential(NoSymbol, null)), ref1) <:< tp2
- } finally {
- skolemizationLevel -= 1
- }
- case (_, et: ExistentialType) =>
- et.withTypeVars(tp1 <:< _, depth)
+ case (_, et: ExistentialType) if et.withTypeVars(tp1 <:< _, depth) =>
+ true
case (RefinedType(parents1, ref1), _) =>
parents1 exists (_ <:< tp2)
@@ -3954,7 +3925,7 @@ A type's typeSymbol should never be inspected directly.
(strippedTypes, quantified)
}
- def lub(ts: List[Type]): Type = lub(ts, maxBaseTypeSeqDepth(ts) + LubGlbMargin)
+ def lub(ts: List[Type]): Type = lub(ts, lubDepth(ts))
/** The least upper bound wrt &lt;:&lt; of a list of types */
def lub(ts: List[Type], depth: Int): Type = {
@@ -4032,22 +4003,22 @@ A type's typeSymbol should never be inspected directly.
}
existentialAbstraction(tparams, lubType)
}
-// if (settings.debug.value) {
-// println(indent + "lub of " + ts + " at depth "+depth)//debug
-// indent = indent + " "
-// assert(indent.length <= 100)
-// }
+ if (printLubs) {
+ println(indent + "lub of " + ts + " at depth "+depth)//debug
+ indent = indent + " "
+ assert(indent.length <= 100)
+ }
val res = if (depth < 0) AnyClass.tpe else lub0(ts)
-// if (settings.debug.value) {
-// indent = indent.substring(0, indent.length() - 2)
-// println(indent + "lub of " + ts + " is " + res)//debug
-// }
+ if (printLubs) {
+ indent = indent.substring(0, indent.length() - 2)
+ println(indent + "lub of " + ts + " is " + res)//debug
+ }
if (ts forall (_.isNotNull)) res.notNull else res
}
val GlbFailure = new Throwable
- def glb(ts: List[Type]): Type = glb(ts, maxBaseTypeSeqDepth(ts) + LubGlbMargin)
+ def glb(ts: List[Type]): Type = glb(ts, lubDepth(ts))
/** The greatest lower bound wrt &lt;:&lt; of a list of types */
private def glb(ts: List[Type], depth: Int): Type = {
@@ -4127,15 +4098,15 @@ A type's typeSymbol should never be inspected directly.
else NothingClass.tpe
}
}
-// if (settings.debug.value) {
-// log(indent + "glb of " + ts + " at depth "+depth)//debug
-// indent = indent + " "
-// }
+ if (settings.debug.value) {
+ println(indent + "glb of " + ts + " at depth "+depth)//debug
+ indent = indent + " "
+ }
val res = if (depth < 0) NothingClass.tpe else glb0(ts)
-// if (settings.debug.value) {
-// indent = indent.substring(0, indent.length() - 2)
-// log(indent + "glb of " + ts + " is " + res)//debug
-// }
+ if (settings.debug.value) {
+ indent = indent.substring(0, indent.length() - 2)
+ log(indent + "glb of " + ts + " is " + res)//debug
+ }
if (ts exists (_.isNotNull)) res.notNull else res
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 5e77092248..d83b581394 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -143,12 +143,12 @@ trait Infer {
* @throws NoInstance
*/
private def solvedTypes(tvars: List[TypeVar], tparams: List[Symbol],
- variances: List[Int], upper: Boolean): List[Type] = {
+ variances: List[Int], upper: Boolean, depth: Int): List[Type] = {
def boundsString(tvar: TypeVar) =
"\n "+
((tvar.constr.lobounds map (_ + " <: " + tvar.origin.typeSymbol.name)) :::
(tvar.constr.hibounds map (tvar.origin.typeSymbol.name + " <: " + _)) mkString ", ")
- if (!solve(tvars, tparams, variances, upper)) {
+ if (!solve(tvars, tparams, variances, upper, depth)) {
// no panic, it's good enough to just guess a solution, we'll find out
// later whether it works.
// throw new DeferredNoInstance(() =>
@@ -448,7 +448,8 @@ trait Infer {
val tvars = tparams map freshVar
if (isCompatible(restpe.instantiateTypeParams(tparams, tvars), pt)) {
try {
- solvedTypes(tvars, tparams, tparams map varianceInType(restpe), false)
+ solvedTypes(tvars, tparams, tparams map varianceInType(restpe),
+ false, lubDepth(List(restpe, pt)))
} catch {
case ex: NoInstance => null
}
@@ -535,7 +536,7 @@ trait Infer {
// check first whether type variables can be fully defined from
// expected result type.
if (!isWeaklyCompatible(restpe.instantiateTypeParams(tparams, tvars), pt)) {
-// just wait and instantiate form the arguments.
+// just wait and instantiate from the arguments.
// that way, we can try to apply an implicit conversion afterwards.
// This case could happen if restpe is not fully defined, so that
// search for an implicit from it to pt fails because of an ambiguity.
@@ -556,7 +557,8 @@ trait Infer {
}
()
}
- val targs = solvedTypes(tvars, tparams, tparams map varianceInTypes(formals), false)
+ val targs = solvedTypes(tvars, tparams, tparams map varianceInTypes(formals),
+ false, lubDepth(formals) max lubDepth(argtpes))
// val res =
List.map2(tparams, targs) {(tparam, targ) =>
if (targ.typeSymbol == NothingClass && (varianceInType(restpe)(tparam) & COVARIANT) == 0) {
@@ -1007,7 +1009,8 @@ trait Infer {
*/
def computeArgs =
try {
- val targs = solvedTypes(tvars, undetparams, undetparams map varianceInType(restpe), true)
+ val targs = solvedTypes(tvars, undetparams, undetparams map varianceInType(restpe),
+ true, lubDepth(List(restpe, pt)))
// checkBounds(tree.pos, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
// no checkBounds here. If we enable it, test bug602 fails.
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 97275ad526..042b7293bb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -28,6 +28,8 @@ trait Typers { self: Analyzer =>
import definitions._
import posAssigner.atPos
+ private final val printTypings = false
+
var appcnt = 0
var idcnt = 0
var selcnt = 0
@@ -2319,6 +2321,10 @@ trait Typers { self: Analyzer =>
error(tree.pos, "illegal variable in pattern alternative")
vble = namer.enterInScope(vble)
}
+ vble.setInfo(new LazyType {
+ // forces a cyclic reference error when dereferenced. See #1049
+ override def complete(sym: Symbol) { sym.info }
+ })
val body1 = typed(body, mode, pt)
trackSetInfo(vble)(
if (treeInfo.isSequenceValued(body)) seqType(body1.tpe)
@@ -3285,7 +3291,7 @@ trait Typers { self: Analyzer =>
tree.tpe = null
if (tree.hasSymbol) tree.symbol = NoSymbol
}
-// Console.println("typing "+tree+", "+context.undetparams);//DEBUG
+ if (printTypings) println("typing "+tree+", "+context.undetparams);//DEBUG
def dropExistential(tp: Type): Type = tp match {
case ExistentialType(tparams, tpe) =>
if (settings.debug.value) println("drop ex "+tree+" "+tp)
@@ -3297,12 +3303,12 @@ trait Typers { self: Analyzer =>
case _ => tp
}
var tree1 = if (tree.tpe ne null) tree else typed1(tree, mode, dropExistential(pt))
-// Console.println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams+", pt = "+pt);//DEBUG
+ if (printTypings) println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams+", pt = "+pt);//DEBUG
tree1.tpe = addAnnotations(tree1, tree1.tpe)
val result = if (tree1.isEmpty || (inIDE && tree1.tpe == null)) tree1 else adapt(tree1, mode, pt)
-// Console.println("adapted "+tree1+":"+tree1.tpe+" to "+pt+", "+context.undetparams);//DEBUG
+ if (printTypings) println("adapted "+tree1+":"+tree1.tpe+" to "+pt+", "+context.undetparams);//DEBUG
// if ((mode & TYPEmode) != 0) println("type: "+tree1+" has type "+tree1.tpe)
result
} catch {