summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-03-12 11:13:41 +0000
committerMartin Odersky <odersky@gmail.com>2007-03-12 11:13:41 +0000
commit661c602630e72f7a9a81e6f21ca5cd6946a9618f (patch)
tree2ade95543be3c135d23aeffa9f68f7716711d6f5
parent439588db9565508147dfad5adba9469ffdc7798c (diff)
downloadscala-661c602630e72f7a9a81e6f21ca5cd6946a9618f.tar.gz
scala-661c602630e72f7a9a81e6f21ca5cd6946a9618f.tar.bz2
scala-661c602630e72f7a9a81e6f21ca5cd6946a9618f.zip
Fixed David Pollacks stack overflow problem.
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala28
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala18
3 files changed, 39 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index c359d166d9..9ddd8df4a7 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -261,6 +261,10 @@ trait Types requires SymbolTable {
def contains(sym: Symbol): boolean =
new ContainsTraverser(sym).traverse(this).result
+ /** Does this type contain a reference to this type */
+ def containsTp(tp: Type): boolean =
+ new ContainsTypeTraverser(tp).traverse(this).result
+
/** Is this type a subtype of that type? */
def <:<(that: Type): boolean = {
if (util.Statistics.enabled) subtypeCount = subtypeCount + 1
@@ -1201,6 +1205,7 @@ trait Types requires SymbolTable {
* Not used after phase `typer'.
*/
case class TypeVar(origin: Type, constr: TypeConstraint) extends Type {
+ //constr.self = this //DEBUG
override def symbol = origin.symbol
override def toString(): String =
if (constr.inst eq null) "<null " + origin + ">"
@@ -1520,10 +1525,19 @@ trait Types requires SymbolTable {
/** A class expressing upper and lower bounds constraints
* for type variables, as well as their instantiations */
class TypeConstraint(lo: List[Type], hi: List[Type]) {
+ //var self: Type = _ //DEBUG
def this() = this(List(), List())
var lobounds: List[Type] = lo
var hibounds: List[Type] = hi
- var inst: Type = NoType
+ private var inst: Type = NoType
+/* debug
+ private var _inst: Type = NoType
+ def inst = _inst
+ def inst_=(tp: Type) {
+ assert(tp == null || !(tp containsTp self), tp)
+ _inst = tp
+ }
+*/
def instantiate(tp: Type): boolean =
if (lobounds.forall(.<:<(tp)) && hibounds.forall(tp.<:<)) {
@@ -1836,6 +1850,18 @@ trait Types requires SymbolTable {
}
/** A map to implement the <code>contains</code> method */
+ class ContainsTypeTraverser(t: Type) extends TypeTraverser {
+ var result = false
+ def traverse(tp: Type): ContainsTypeTraverser = {
+ if (!result) {
+ if (tp eq t) result = true
+ else mapOver(tp)
+ }
+ this
+ }
+ }
+
+ /** A map to implement the <code>contains</code> method */
object ErroneousTraverser extends TypeTraverser {
var result: boolean = _
def traverse(tp: Type): TypeTraverser = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index ed1e1a04d0..c184a62784 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -140,8 +140,8 @@ trait Infer requires Analyzer {
val up = if (variance != CONTRAVARIANT) upper else !upper
tvar.constr.inst = null
val bound: Type = if (up) tparam.info.bounds.hi else tparam.info.bounds.lo
- //Console.println("solveOne0 "+tvar+" "+config+" "+bound);//DEBUG
- var cyclic = false
+ // Console.println("solveOne0 "+tvar+" "+config+" "+bound);//DEBUG
+ var cyclic = bound contains tparam
for (val (tvar2, (tparam2, variance2)) <- config) {
if (tparam2 != tparam &&
((bound contains tparam2) ||
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index cfd18731b2..431d21f5f8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1871,14 +1871,16 @@ trait Typers requires Analyzer {
// update `pre' to be `sym's prefix type in case it is an imported member,
// and compute value of:
- // imported symbols take precedence over package-owned symbols in different
- // compilation units
- if (defSym.exists && impSym.exists &&
- defSym.owner.isPackageClass &&
- (!currentRun.compiles(defSym) ||
- (context.unit ne null) && defSym.sourceFile != context.unit.source.file))
- defSym = NoSymbol
-
+ if (defSym.exists && impSym.exists) {
+ // imported symbols take precedence over package-owned symbols in different
+ // compilation units. Defined symbols take precedence over errenous imports.
+ if (defSym.owner.isPackageClass &&
+ (!currentRun.compiles(defSym) ||
+ (context.unit ne null) && defSym.sourceFile != context.unit.source.file))
+ defSym = NoSymbol
+ else if (impSym.isError)
+ impSym = NoSymbol
+ }
if (defSym.exists) {
if (impSym.exists)
ambiguousError(