From 661c602630e72f7a9a81e6f21ca5cd6946a9618f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 12 Mar 2007 11:13:41 +0000 Subject: Fixed David Pollacks stack overflow problem. --- src/compiler/scala/tools/nsc/symtab/Types.scala | 28 +++++++++++++++++++++- .../scala/tools/nsc/typechecker/Infer.scala | 4 ++-- .../scala/tools/nsc/typechecker/Typers.scala | 18 +++++++------- 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) "" @@ -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.<:<)) { @@ -1835,6 +1849,18 @@ trait Types requires SymbolTable { } } + /** A map to implement the contains 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 contains method */ object ErroneousTraverser extends TypeTraverser { var result: boolean = _ 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( -- cgit v1.2.3