diff options
author | Martin Odersky <odersky@gmail.com> | 2008-01-23 11:18:51 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2008-01-23 11:18:51 +0000 |
commit | fe9a3a692e85149351c4d14cca2e15771b5309f9 (patch) | |
tree | 506a4121e37bc15b917cb0152c4ad0228e811599 | |
parent | a5692b1f4060c0be1da97f384277e02a0172aac5 (diff) | |
download | scala-fe9a3a692e85149351c4d14cca2e15771b5309f9.tar.gz scala-fe9a3a692e85149351c4d14cca2e15771b5309f9.tar.bz2 scala-fe9a3a692e85149351c4d14cca2e15771b5309f9.zip |
fixed #400
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Infer.scala | 33 |
2 files changed, 23 insertions, 14 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index a1dcc6f6ef..1886c40af1 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -2494,7 +2494,9 @@ A type's typeSymbol should never be inspected directly. */ object rawToExistential extends TypeMap { def apply(tp: Type): Type = tp match { - case TypeRef(pre, sym, List()) if (sym.hasFlag(JAVA) && !sym.typeParams.isEmpty) => + case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty && sym.hasFlag(JAVA) => + // note: it's important to write the two tests in this order, + // as only typeParams forces the classfile to be read. See #400 val eparams = typeParamsToExistentials(sym, sym.typeParams) existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe))) case _ => diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index bf5c599ae8..116543fc53 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -78,10 +78,6 @@ trait Infer { override def getMessage(): String = getmsg() } - /*private*/ object instantiateMap extends TypeMap { - def apply(t: Type): Type = instantiate(t) - } - /** map every TypeVar to its constraint.inst field. * throw a NoInstance exception if a NoType or WildcardType is encountered. * @@ -89,15 +85,26 @@ trait Infer { * @return ... * @throws NoInstance */ - def instantiate(tp: Type): Type = tp match { - case WildcardType | NoType => - throw new NoInstance("undetermined type") - case TypeVar(origin, constr) => - if (constr.inst != NoType) instantiate(constr.inst) - else throw new DeferredNoInstance(() => - "no unique instantiation of type variable " + origin + " could be found") - case _ => - instantiateMap.mapOver(tp) + object instantiate extends TypeMap { + private var excludedVars = scala.collection.immutable.Set[TypeVar]() + def apply(tp: Type): Type = tp match { + case WildcardType | NoType => + throw new NoInstance("undetermined type") + case tv @ TypeVar(origin, constr) => + if (constr.inst == NoType) { + throw new DeferredNoInstance(() => + "no unique instantiation of type variable " + origin + " could be found") + } else if (excludedVars contains tv) { + throw new NoInstance("cyclic instantiation") + } else { + excludedVars += tv + val res = apply(constr.inst) + excludedVars -= tv + res + } + case _ => + mapOver(tp) + } } /** Is type fully defined, i.e. no embedded anytypes or wildcards in it? |