summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2008-01-23 11:18:51 +0000
committerMartin Odersky <odersky@gmail.com>2008-01-23 11:18:51 +0000
commitfe9a3a692e85149351c4d14cca2e15771b5309f9 (patch)
tree506a4121e37bc15b917cb0152c4ad0228e811599 /src
parenta5692b1f4060c0be1da97f384277e02a0172aac5 (diff)
downloadscala-fe9a3a692e85149351c4d14cca2e15771b5309f9.tar.gz
scala-fe9a3a692e85149351c4d14cca2e15771b5309f9.tar.bz2
scala-fe9a3a692e85149351c4d14cca2e15771b5309f9.zip
fixed #400
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala33
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?