summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala73
-rw-r--r--test/files/neg/t1705.check7
-rwxr-xr-xtest/files/neg/t1705.scala35
-rwxr-xr-xtest/files/run/existentials.scala2
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 {