diff options
author | Martin Odersky <odersky@gmail.com> | 2009-08-10 09:57:54 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-08-10 09:57:54 +0000 |
commit | 1e15c075c1ae03cf1d356e45606894efdc57093a (patch) | |
tree | e0240cca1416d74cdf4bf47103f6acb2c87fb4a7 | |
parent | dd8009b190fc1f53f98f1313b6292579af79e309 (diff) | |
download | scala-1e15c075c1ae03cf1d356e45606894efdc57093a.tar.gz scala-1e15c075c1ae03cf1d356e45606894efdc57093a.tar.bz2 scala-1e15c075c1ae03cf1d356e45606894efdc57093a.zip |
fixed t1705.
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Symbols.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 73 | ||||
-rw-r--r-- | test/files/neg/t1705.check | 7 | ||||
-rwxr-xr-x | test/files/neg/t1705.scala | 35 | ||||
-rwxr-xr-x | test/files/run/existentials.scala | 2 |
5 files changed, 57 insertions, 62 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index c551fcc240..b76f169552 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -1410,7 +1410,7 @@ trait Symbols { if (settings.debug.value) "package class" else "package" else if (isModuleClass) if (settings.debug.value) "singleton class" else "object" - else if (isAnonymousClass) "template" + else if (isAnonymousClass) "anonymous class" else if (isRefinementClass) "" else if (isTrait) "trait" else if (isClass) "class" diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 8056c2794e..30098885ff 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -746,7 +746,7 @@ trait Typers { self: Analyzer => protected def adapt(tree: Tree, mode: Int, pt: Type): Tree = tree.tpe match { case atp @ AnnotatedType(_, _, _) if canAdaptAnnotations(tree, mode, pt) => // (-1) adaptAnnotations(tree, mode, pt) - case ct @ ConstantType(value) if ((mode & (TYPEmode | FUNmode)) == 0 && (ct <:< pt)) => // (0) + case ct @ ConstantType(value) if ((mode & (TYPEmode | FUNmode)) == 0 && (ct <:< pt) && !onlyPresentation) => // (0) treeCopy.Literal(tree, value) case OverloadedType(pre, alts) if ((mode & FUNmode) == 0) => // (1) inferExprAlternative(tree, pt) @@ -1595,11 +1595,9 @@ trait Typers { self: Analyzer => namer.enterSyms(block.stats) for (stat <- block.stats) { if (onlyPresentation && stat.isDef) { - if (stat.isDef) { - var e = context.scope.lookupEntry(stat.symbol.name) - while ((e ne null) && (e.sym ne stat.symbol)) e = e.tail - if (e eq null) context.scope.enter(stat.symbol) - } + var e = context.scope.lookupEntry(stat.symbol.name) + while ((e ne null) && (e.sym ne stat.symbol)) e = e.tail + if (e eq null) context.scope.enter(stat.symbol) } enterLabelDef(stat) } @@ -2536,9 +2534,8 @@ trait Typers { self: Analyzer => } var localSyms = collection.immutable.Set[Symbol]() var boundSyms = collection.immutable.Set[Symbol]() - var localInstances = collection.immutable.Map[SymInstance, Symbol]() def isLocal(sym: Symbol): Boolean = - if (sym == NoSymbol) false + if (sym == NoSymbol || sym.isRefinementClass || sym.isLocalDummy) false else if (owner == NoSymbol) tree exists (defines(_, sym)) else containsDef(owner, sym) || isRawParameter(sym) def containsLocal(tp: Type): Boolean = @@ -2559,33 +2556,19 @@ trait Typers { self: Analyzer => // add all local symbols of `tp' to `localSyms' // expanding higher-kinded types into individual copies for each instance. def addLocals(tp: Type) { + val remainingSyms = new ListBuffer[Symbol] def addIfLocal(sym: Symbol, tp: Type) { - if (sym != NoSymbol && !sym.isRefinementClass && isLocal(sym) && - !(localSyms contains sym) && !(boundSyms contains sym) ) { + if (isLocal(sym) && !localSyms.contains(sym) && !boundSyms.contains(sym)) { if (sym.typeParams.isEmpty) { localSyms += sym - addLocals(sym.existentialBound) - } else if (tp.typeArgs.isEmpty) { - unit.error(tree.pos, - "implementation restriction: can't existentially abstract over higher-kinded type" + tp) + remainingSyms += sym } else { - val inst = new SymInstance(sym, tp) - if (!(localInstances contains inst)) { - val bound = sym.existentialBound match { - case PolyType(tparams, restpe) => - restpe.subst(tparams, tp.typeArgs) - case t => - t - } - val local = trackSetInfo(recycle(sym.owner.newAbstractType( - sym.pos, unit.fresh.newName(sym.pos, sym.name.toString)) - .setFlag(sym.flags)))(bound) - localInstances += (inst -> local) - addLocals(bound) - } + unit.error(tree.pos, + "can't existentially abstract over parameterized type " + tp) } } } + for (t <- tp) { t match { case ExistentialType(tparams, _) => @@ -2608,42 +2591,12 @@ trait Typers { self: Analyzer => addIfLocal(t.termSymbol, t) addIfLocal(t.typeSymbol, t) } - } - - object substLocals extends TypeMap { - override val dropNonConstraintAnnotations = true - - def apply(t: Type): Type = t match { - case TypeRef(_, sym, args) if (sym.isLocal && args.length > 0) => - localInstances.get(new SymInstance(sym, t)) match { - case Some(local) => typeRef(NoPrefix, local, List()) - case None => mapOver(t) - } - case _ => mapOver(t) - } - - override def mapOver(arg: Tree, giveup: ()=>Nothing) = { - object substLocalTrees extends TypeMapTransformer { - override def transform(tr: Tree) = { - localInstances.get(new SymInstance(tr.symbol, tr.tpe)) match { - case Some(local) => - Ident(local.existentialToString) - .setSymbol(tr.symbol).copyAttrs(tr).setType( - typeRef(NoPrefix, local, List())) - - case None => super.transform(tr) - } - } - } - - substLocalTrees.transform(arg) - } + for (sym <- remainingSyms) addLocals(sym.existentialBound) } val normalizedTpe = normalizeLocals(tree.tpe) addLocals(normalizedTpe) - - packSymbols(localSyms.toList ::: localInstances.values.toList, substLocals(normalizedTpe)) + packSymbols(localSyms.toList, normalizedTpe) } protected def typedExistentialTypeTree(tree: ExistentialTypeTree, mode: Int): Tree = { diff --git a/test/files/neg/t1705.check b/test/files/neg/t1705.check new file mode 100644 index 0000000000..7f75bd0fb5 --- /dev/null +++ b/test/files/neg/t1705.check @@ -0,0 +1,7 @@ +t1705.scala:9: error: can't existentially abstract over parameterized type this.T[Z] + val c = new C{ + ^ +t1705.scala:14: error: can't existentially abstract over parameterized type C[String] + val x1 = { + ^ +two errors found diff --git a/test/files/neg/t1705.scala b/test/files/neg/t1705.scala new file mode 100755 index 0000000000..fabdca0ec6 --- /dev/null +++ b/test/files/neg/t1705.scala @@ -0,0 +1,35 @@ +package trials +object crashing { + trait C { + abstract class T[A] { + def f[Z] (a:T[Z]) : T[A] + } + } + abstract class Thing { + val c = new C{ + class T[A](a:A) { + def f[Z](t:T[Z]) = new T(a) + } + } + val x1 = { + class C[T] { val x: T } + new C[String] + } + } +} +/* + +Infinite loop in Typer.addLocals. Printing all calls to it: + +addLocals: Unit +addLocals: this.T[A] +addLocals: java.lang.Object with crashing.C{ ... } +addLocals: >: Nothing <: java.lang.Object with crashing.C{type T[A] <: java.lang.Object with ScalaObject{def f[Z](this.T[Z]): this.T[A]}} +addLocals: >: Nothing <: java.lang.Object with ScalaObject{def f[Z](this.T[Z]): this.T[Z]} +addLocals: >: Nothing <: java.lang.Object with ScalaObject{def f[Z](this.T[Z]): this.T[Z]} +addLocals: >: Nothing <: java.lang.Object with ScalaObject{def f[Z](this.T[Z]): this.T[Z]} +[...] +* + C { type T[A] <: { def f[Z]: T[Z] => T[A] } } + +*/ diff --git a/test/files/run/existentials.scala b/test/files/run/existentials.scala index 469112b392..471f8fe779 100755 --- a/test/files/run/existentials.scala +++ b/test/files/run/existentials.scala @@ -52,7 +52,7 @@ object Bug1189 { object Test extends Application { - val x = { class I[T]; (new C(new I[String]), new C(new I[Int])) } + val x = { class I; class J; (new C(new I), new C(new J)) } val y: (C[X], C[Y]) forSome { type X; type Y } = x def foo(x : Counter[T] { def name : String } forSome { type T }) = x match { |