summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala28
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala8
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala65
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala8
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala24
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala4
-rw-r--r--src/partest/scala/tools/partest/CompilerTest.scala27
-rw-r--r--src/partest/scala/tools/partest/DirectTest.scala32
-rw-r--r--test/files/run/existentials-in-compiler.check156
-rw-r--r--test/files/run/existentials-in-compiler.scala83
10 files changed, 385 insertions, 50 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index e05ac1087b..5b2c61701d 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -586,14 +586,6 @@ trait Definitions extends reflect.api.StandardDefinitions {
case _ => NoType
}
- /** To avoid unchecked warnings on polymorphic classes, translate
- * a Foo[T] into a Foo[_] for use in the pattern matcher.
- */
- def typeCaseType(clazz: Symbol) = clazz.tpe.normalize match {
- case TypeRef(_, sym, args) if args.nonEmpty => newExistentialType(sym.typeParams, clazz.tpe)
- case tp => tp
- }
-
def seqType(arg: Type) = appliedType(SeqClass.typeConstructor, List(arg))
def arrayType(arg: Type) = appliedType(ArrayClass.typeConstructor, List(arg))
def byNameType(arg: Type) = appliedType(ByNameParamClass.typeConstructor, List(arg))
@@ -609,6 +601,26 @@ trait Definitions extends reflect.api.StandardDefinitions {
def vmClassType(arg: Type): Type = ClassType(arg)
def vmSignature(sym: Symbol, info: Type): String = signature(info) // !!!
+ /** Given a class symbol C with type parameters T1, T2, ... Tn
+ * which have upper/lower bounds LB1/UB1, LB1/UB2, ..., LBn/UBn,
+ * returns an existential type of the form
+ *
+ * C[E1, ..., En] forSome { E1 >: LB1 <: UB1 ... en >: LBn <: UBn }.
+ */
+ def classExistentialType(clazz: Symbol): Type =
+ newExistentialType(clazz.typeParams, clazz.tpe)
+
+ /** Given type U, creates a Type representing Class[_ <: U].
+ */
+ def boundedClassType(upperBound: Type) =
+ appliedTypeAsUpperBounds(ClassClass.typeConstructor, List(upperBound))
+
+ /** To avoid unchecked warnings on polymorphic classes, translate
+ * a Foo[T] into a Foo[_] for use in the pattern matcher.
+ */
+ @deprecated("Use classExistentialType", "2.10.0")
+ def typeCaseType(clazz: Symbol): Type = classExistentialType(clazz)
+
//
// .NET backend
//
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index fb827b0658..1973a97279 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -120,9 +120,11 @@ abstract class SymbolTable extends api.Universe
try op
finally phase = current
}
-
- @inline final def afterPhase[T](ph: Phase)(op: => T): T =
- atPhase(ph.next)(op)
+ /** Since when it is to be "at" a phase is inherently ambiguous,
+ * a couple unambiguously named methods.
+ */
+ @inline final def beforePhase[T](ph: Phase)(op: => T): T = atPhase(ph)(op)
+ @inline final def afterPhase[T](ph: Phase)(op: => T): T = atPhase(ph.next)(op)
@inline final def atPhaseNotLaterThan[T](target: Phase)(op: => T): T =
if (target != NoPhase && phase.id > target.id) atPhase(target)(op) else op
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index cd44b700c1..6295c089b2 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -2433,25 +2433,37 @@ trait Types extends api.Types { self: SymbolTable =>
case _ =>
List()
}
-
+ /** An existential can only be printed with wildcards if:
+ * - the underlying type is a typeref
+ * - where there is a 1-to-1 correspondence between underlying's typeargs and quantified
+ * - and none of the existential parameters is referenced from anywhere else in the type
+ * - and none of the existential parameters are singleton types
+ */
+ private def isRepresentableWithWildcards = !settings.debug.value && {
+ val qset = quantified.toSet
+ !qset.exists(_.isSingletonExistential) && (underlying match {
+ case TypeRef(_, sym, args) =>
+ sameLength(args, quantified) && {
+ args forall { arg =>
+ qset(arg.typeSymbol) && !qset.exists(arg.typeSymbol.info.bounds contains _)
+ }
+ }
+ case _ => false
+ })
+ }
override def safeToString: String = {
- if (!(quantified exists (_.isSingletonExistential)) && !settings.debug.value)
- // try to represent with wildcards first
- underlying match {
- case TypeRef(pre, sym, args) if args.nonEmpty =>
- val wargs = wildcardArgsString(quantified.toSet, args)
- if (sameLength(wargs, args))
- return TypeRef(pre, sym, List()) + wargs.mkString("[", ", ", "]")
- case _ =>
- }
- var ustr = underlying.toString
+ def clauses = {
+ val str = quantified map (_.existentialToString) mkString (" forSome { ", "; ", " }")
+ if (settings.explaintypes.value) "(" + str + ")" else str
+ }
underlying match {
- case MethodType(_, _) | NullaryMethodType(_) | PolyType(_, _) => ustr = "("+ustr+")"
+ case TypeRef(pre, sym, args) if isRepresentableWithWildcards =>
+ "" + TypeRef(pre, sym, Nil) + wildcardArgsString(quantified.toSet, args).mkString("[", ", ", "]")
+ case MethodType(_, _) | NullaryMethodType(_) | PolyType(_, _) =>
+ "(" + underlying + ")" + clauses
case _ =>
+ "" + underlying + clauses
}
- val str =
- ustr+(quantified map (_.existentialToString) mkString(" forSome { ", "; ", " }"))
- if (settings.explaintypes.value) "("+str+")" else str
}
override def cloneInfo(owner: Symbol) =
@@ -3260,6 +3272,25 @@ trait Types extends api.Types { self: SymbolTable =>
case WildcardType => tycon // needed for neg/t0226
case _ => abort(debugString(tycon))
}
+
+ /** A creator for existential types where the type arguments,
+ * rather than being applied directly, are interpreted as the
+ * upper bounds of unknown types. For instance if the type argument
+ * list given is List(AnyRefClass), the resulting type would be
+ * e.g. Set[_ <: AnyRef] rather than Set[AnyRef] .
+ */
+ def appliedTypeAsUpperBounds(tycon: Type, args: List[Type]): Type = {
+ tycon match {
+ case TypeRef(pre, sym, _) if sameLength(sym.typeParams, args) =>
+ val eparams = typeParamsToExistentials(sym)
+ val bounds = args map (TypeBounds upper _)
+ (eparams, bounds).zipped foreach (_ setInfo _)
+
+ newExistentialType(eparams, typeRef(pre, sym, eparams map (_.tpe)))
+ case _ =>
+ appliedType(tycon, args)
+ }
+ }
/** A creator for type parameterizations that strips empty type parameter lists.
* Use this factory method to indicate the type has kind * (it's a polymorphic value)
@@ -3845,6 +3876,8 @@ trait Types extends api.Types { self: SymbolTable =>
eparams map (_ substInfo (tparams, eparams))
}
+ def typeParamsToExistentials(clazz: Symbol): List[Symbol] =
+ typeParamsToExistentials(clazz, clazz.typeParams)
// note: it's important to write the two tests in this order,
// as only typeParams forces the classfile to be read. See #400
@@ -3876,7 +3909,7 @@ trait Types extends api.Types { self: SymbolTable =>
if (expanded contains sym) AnyRefClass.tpe
else try {
expanded += sym
- val eparams = mapOver(typeParamsToExistentials(sym, sym.typeParams))
+ val eparams = mapOver(typeParamsToExistentials(sym))
existentialAbstraction(eparams, typeRef(apply(pre), sym, eparams map (_.tpe)))
} finally {
expanded -= sym
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 18735cafe2..4493188b31 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -807,6 +807,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
def currentRun: Run = curRun
def currentUnit: CompilationUnit = if (currentRun eq null) NoCompilationUnit else currentRun.currentUnit
def currentSource: SourceFile = if (currentUnit.exists) currentUnit.source else lastSeenSourceFile
+
+ @inline final def afterTyper[T](op: => T): T = afterPhase(currentRun.typerPhase)(op)
+ @inline final def beforeErasure[T](op: => T): T = beforePhase(currentRun.erasurePhase)(op)
+ @inline final def afterErasure[T](op: => T): T = afterPhase(currentRun.erasurePhase)(op)
/** Don't want to introduce new errors trying to report errors,
* so swallow exceptions.
@@ -1114,7 +1118,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
lazy val trackers = currentRun.units.toList map (x => SymbolTracker(x))
def snapshot() = {
inform("\n[[symbol layout at end of " + phase + "]]")
- atPhase(phase.next) {
+ afterPhase(phase) {
trackers foreach { t =>
t.snapshot()
inform(t.show("Heading from " + phase.prev.name + " to " + phase.name))
@@ -1389,7 +1393,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
def printAllUnits() {
print("[[syntax trees at end of " + phase + "]]")
- atPhase(phase.next) { currentRun.units foreach (treePrinter.print(_)) }
+ afterPhase(phase) { currentRun.units foreach (treePrinter.print(_)) }
}
private def findMemberFromRoot(fullName: Name): Symbol = {
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index fe479a5375..5f84d765b9 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -44,22 +44,16 @@ abstract class Erasure extends AddInterfaces
// class object is that of java.lang.Integer, not Int.
//
// TODO: If T is final, return type could be Class[T]. Should it?
- def getClassReturnType(tp: Type): Type = {
- val sym = tp.typeSymbol
-
- if (phase.erasedTypes) ClassClass.tpe
- else if (isValueClass(sym)) ClassType(tp.widen)
- else {
- val eparams = typeParamsToExistentials(ClassClass, ClassClass.typeParams)
- val upperBound = (
- if (isPhantomClass(sym)) AnyClass.tpe
+ def getClassReturnType(tpe: Type): Type = {
+ if (phase.erasedTypes) ClassClass.tpe else {
+ val tp = tpe.widen.normalize
+ val sym = tp.typeSymbol
+
+ if (isValueClass(sym)) ClassType(tp)
+ else boundedClassType(
+ if (isPhantomClass(sym)) ObjectClass.tpe
else if (sym.isLocalClass) intersectionDominator(tp.parents)
- else tp.widen
- )
-
- existentialAbstraction(
- eparams,
- ClassType(eparams.head setInfo TypeBounds.upper(upperBound) tpe)
+ else tp
)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 4ea21b1c44..cf90577959 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -116,7 +116,7 @@ trait SyntheticMethods extends ast.TreeDSL {
*/
def canEqualMethod: Tree = (
createMethod(nme.canEqual_, List(AnyClass.tpe), BooleanClass.tpe)(m =>
- Ident(m.firstParam) IS_OBJ typeCaseType(clazz))
+ Ident(m.firstParam) IS_OBJ classExistentialType(clazz))
)
/** The equality method for case classes.
@@ -132,7 +132,7 @@ trait SyntheticMethods extends ast.TreeDSL {
*/
def equalsClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m =>
val arg0 = Ident(m.firstParam)
- val thatTest = gen.mkIsInstanceOf(arg0, typeCaseType(clazz), true, false)
+ val thatTest = gen.mkIsInstanceOf(arg0, classExistentialType(clazz), true, false)
val thatCast = gen.mkCast(arg0, clazz.tpe)
def argsBody: Tree = {
diff --git a/src/partest/scala/tools/partest/CompilerTest.scala b/src/partest/scala/tools/partest/CompilerTest.scala
new file mode 100644
index 0000000000..dd06c051a4
--- /dev/null
+++ b/src/partest/scala/tools/partest/CompilerTest.scala
@@ -0,0 +1,27 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.partest
+
+import scala.tools.nsc._
+
+/** For testing compiler internals directly.
+ * Each source code string in "sources" will be compiled, and
+ * the check function will be called with the source code and the
+ * resulting CompilationUnit. The check implementation should
+ * test for what it wants to test and fail (via assert or other
+ * exception) if it is not happy.
+ */
+abstract class CompilerTest extends DirectTest {
+ def check(source: String, unit: global.CompilationUnit): Unit
+
+ lazy val global: Global = newCompiler()
+ lazy val units = compilationUnits(global)(sources: _ *)
+
+ override def extraSettings = "-usejavacp -d " + testOutput.path
+
+ def sources: List[String] = List(code)
+ def show() = (sources, units).zipped foreach check
+}
diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala
index be8cac9147..74f511aa4e 100644
--- a/src/partest/scala/tools/partest/DirectTest.scala
+++ b/src/partest/scala/tools/partest/DirectTest.scala
@@ -35,13 +35,37 @@ abstract class DirectTest extends App {
s processArguments (allArgs, true)
s
}
- // compile the code, optionally first adding to the settings
- def compile(args: String*) = {
+ // new compiler
+ def newCompiler(args: String*): Global = {
val settings = newSettings((CommandLineParser tokenize extraSettings) ++ args.toList)
- val global = new Global(settings)
- new global.Run compileSources List(new BatchSourceFile("<partest>", code))
+ new Global(settings)
+ }
+ def newSources(sourceCodes: String*) = sourceCodes.toList.zipWithIndex map {
+ case (src, idx) => new BatchSourceFile("newSource" + (idx + 1), src)
+ }
+ def compileString(global: Global)(sourceCode: String): Boolean = {
+ withRun(global)(_ compileSources newSources(sourceCode))
!global.reporter.hasErrors
}
+ def compilationUnits(global: Global)(sourceCodes: String*): List[global.CompilationUnit] = {
+ val units = withRun(global) { run =>
+ run compileSources newSources(sourceCodes: _*)
+ run.units.toList
+ }
+ if (global.reporter.hasErrors) {
+ global.reporter.flush()
+ sys.error("Compilation failure.")
+ }
+ units
+ }
+
+ def withRun[T](global: Global)(f: global.Run => T): T = {
+ global.reporter.reset()
+ f(new global.Run)
+ }
+
+ // compile the code, optionally first adding to the settings
+ def compile(args: String*) = compileString(newCompiler(args: _*))(code)
/** Constructor/main body **/
try show()
diff --git a/test/files/run/existentials-in-compiler.check b/test/files/run/existentials-in-compiler.check
new file mode 100644
index 0000000000..c8040a4cb1
--- /dev/null
+++ b/test/files/run/existentials-in-compiler.check
@@ -0,0 +1,156 @@
+abstract trait Bippy[A <: AnyRef,B] extends Object
+ extest.Bippy[_ <: AnyRef, _]
+
+abstract trait BippyBud[A <: AnyRef,B,C <: List[A]] extends Object
+ extest.BippyBud[A,B,C] forSome { A <: AnyRef; B; C <: List[A] }
+
+abstract trait BippyLike[A <: AnyRef,B <: List[A],This <: extest.BippyLike[A,B,This] with extest.Bippy[A,B]] extends Object
+ extest.BippyLike[A,B,This] forSome { A <: AnyRef; B <: List[A]; This <: extest.BippyLike[A,B,This] with extest.Bippy[A,B] }
+
+abstract trait Contra[-A >: AnyRef,-B] extends Object
+ extest.Contra[_ >: AnyRef, _]
+
+abstract trait ContraLike[-A >: AnyRef,-B >: List[A]] extends Object
+ extest.ContraLike[A,B] forSome { -A >: AnyRef; -B >: List[A] }
+
+abstract trait Cov01[+A <: AnyRef,+B] extends Object
+ extest.Cov01[_ <: AnyRef, _]
+
+abstract trait Cov02[+A <: AnyRef,B] extends Object
+ extest.Cov02[_ <: AnyRef, _]
+
+abstract trait Cov03[+A <: AnyRef,-B] extends Object
+ extest.Cov03[_ <: AnyRef, _]
+
+abstract trait Cov04[A <: AnyRef,+B] extends Object
+ extest.Cov04[_ <: AnyRef, _]
+
+abstract trait Cov05[A <: AnyRef,B] extends Object
+ extest.Cov05[_ <: AnyRef, _]
+
+abstract trait Cov06[A <: AnyRef,-B] extends Object
+ extest.Cov06[_ <: AnyRef, _]
+
+abstract trait Cov07[-A <: AnyRef,+B] extends Object
+ extest.Cov07[_ <: AnyRef, _]
+
+abstract trait Cov08[-A <: AnyRef,B] extends Object
+ extest.Cov08[_ <: AnyRef, _]
+
+abstract trait Cov09[-A <: AnyRef,-B] extends Object
+ extest.Cov09[_ <: AnyRef, _]
+
+abstract trait Cov11[+A <: AnyRef,+B <: List[_]] extends Object
+ extest.Cov11[_ <: AnyRef, _ <: List[_]]
+
+abstract trait Cov12[+A <: AnyRef,B <: List[_]] extends Object
+ extest.Cov12[_ <: AnyRef, _ <: List[_]]
+
+abstract trait Cov13[+A <: AnyRef,-B <: List[_]] extends Object
+ extest.Cov13[_ <: AnyRef, _ <: List[_]]
+
+abstract trait Cov14[A <: AnyRef,+B <: List[_]] extends Object
+ extest.Cov14[_ <: AnyRef, _ <: List[_]]
+
+abstract trait Cov15[A <: AnyRef,B <: List[_]] extends Object
+ extest.Cov15[_ <: AnyRef, _ <: List[_]]
+
+abstract trait Cov16[A <: AnyRef,-B <: List[_]] extends Object
+ extest.Cov16[_ <: AnyRef, _ <: List[_]]
+
+abstract trait Cov17[-A <: AnyRef,+B <: List[_]] extends Object
+ extest.Cov17[_ <: AnyRef, _ <: List[_]]
+
+abstract trait Cov18[-A <: AnyRef,B <: List[_]] extends Object
+ extest.Cov18[_ <: AnyRef, _ <: List[_]]
+
+abstract trait Cov19[-A <: AnyRef,-B <: List[_]] extends Object
+ extest.Cov19[_ <: AnyRef, _ <: List[_]]
+
+abstract trait Cov21[+A,+B] extends Object
+ extest.Cov21[_, _]
+
+abstract trait Cov22[+A,B] extends Object
+ extest.Cov22[_, _]
+
+abstract trait Cov23[+A,-B] extends Object
+ extest.Cov23[_, _]
+
+abstract trait Cov24[A,+B] extends Object
+ extest.Cov24[_, _]
+
+abstract trait Cov25[A,B] extends Object
+ extest.Cov25[_, _]
+
+abstract trait Cov26[A,-B] extends Object
+ extest.Cov26[_, _]
+
+abstract trait Cov27[-A,+B] extends Object
+ extest.Cov27[_, _]
+
+abstract trait Cov28[-A,B] extends Object
+ extest.Cov28[_, _]
+
+abstract trait Cov29[-A,-B] extends Object
+ extest.Cov29[_, _]
+
+abstract trait Cov31[+A,+B,C <: (A, B)] extends Object
+ extest.Cov31[A,B,C] forSome { +A; +B; C <: (A, B) }
+
+abstract trait Cov32[+A,B,C <: (A, B)] extends Object
+ extest.Cov32[A,B,C] forSome { +A; B; C <: (A, B) }
+
+abstract trait Cov33[+A,-B,C <: (A, _$10) forSome { type _$10 }] extends Object
+ extest.Cov33[A,B,C] forSome { +A; -B; C <: (A, _$10) forSome { type _$10 } }
+
+abstract trait Cov34[A,+B,C <: (A, B)] extends Object
+ extest.Cov34[A,B,C] forSome { A; +B; C <: (A, B) }
+
+abstract trait Cov35[A,B,C <: (A, B)] extends Object
+ extest.Cov35[A,B,C] forSome { A; B; C <: (A, B) }
+
+abstract trait Cov36[A,-B,C <: (A, _$11) forSome { type _$11 }] extends Object
+ extest.Cov36[A,B,C] forSome { A; -B; C <: (A, _$11) forSome { type _$11 } }
+
+abstract trait Cov37[-A,+B,C <: (_$12, B) forSome { type _$12 }] extends Object
+ extest.Cov37[A,B,C] forSome { -A; +B; C <: (_$12, B) forSome { type _$12 } }
+
+abstract trait Cov38[-A,B,C <: (_$13, B) forSome { type _$13 }] extends Object
+ extest.Cov38[A,B,C] forSome { -A; B; C <: (_$13, B) forSome { type _$13 } }
+
+abstract trait Cov39[-A,-B,C <: Tuple2[_, _]] extends Object
+ extest.Cov39[_, _, _ <: Tuple2[_, _]]
+
+abstract trait Cov41[+A >: Null,+B] extends Object
+ extest.Cov41[_ >: Null, _]
+
+abstract trait Cov42[+A >: Null,B] extends Object
+ extest.Cov42[_ >: Null, _]
+
+abstract trait Cov43[+A >: Null,-B] extends Object
+ extest.Cov43[_ >: Null, _]
+
+abstract trait Cov44[A >: Null,+B] extends Object
+ extest.Cov44[_ >: Null, _]
+
+abstract trait Cov45[A >: Null,B] extends Object
+ extest.Cov45[_ >: Null, _]
+
+abstract trait Cov46[A >: Null,-B] extends Object
+ extest.Cov46[_ >: Null, _]
+
+abstract trait Cov47[-A >: Null,+B] extends Object
+ extest.Cov47[_ >: Null, _]
+
+abstract trait Cov48[-A >: Null,B] extends Object
+ extest.Cov48[_ >: Null, _]
+
+abstract trait Cov49[-A >: Null,-B] extends Object
+ extest.Cov49[_ >: Null, _]
+
+abstract trait Covariant[+A <: AnyRef,+B] extends Object
+ extest.Covariant[_ <: AnyRef, _]
+
+abstract trait CovariantLike[+A <: AnyRef,+B <: List[A],+This <: extest.CovariantLike[A,B,This] with extest.Covariant[A,B]] extends Object
+ extest.CovariantLike[A,B,This] forSome { +A <: AnyRef; +B <: List[A]; +This <: extest.CovariantLike[A,B,This] with extest.Covariant[A,B] }
+
diff --git a/test/files/run/existentials-in-compiler.scala b/test/files/run/existentials-in-compiler.scala
new file mode 100644
index 0000000000..e4f6920145
--- /dev/null
+++ b/test/files/run/existentials-in-compiler.scala
@@ -0,0 +1,83 @@
+import scala.tools.nsc._
+import scala.tools.partest.CompilerTest
+import scala.collection.{ mutable, immutable, generic }
+
+object Test extends CompilerTest {
+ import global._
+ import definitions._
+
+ def code = """
+package extest {
+ trait Bippy[A <: AnyRef, B] { } // wildcards
+ trait BippyLike[A <: AnyRef, B <: List[A], This <: BippyLike[A, B, This] with Bippy[A, B]] // no wildcards
+ trait BippyBud[A <: AnyRef, B, C <: List[A]]
+
+ trait Cov01[+A <: AnyRef, +B] { }
+ trait Cov02[+A <: AnyRef, B] { }
+ trait Cov03[+A <: AnyRef, -B] { }
+ trait Cov04[ A <: AnyRef, +B] { }
+ trait Cov05[ A <: AnyRef, B] { }
+ trait Cov06[ A <: AnyRef, -B] { }
+ trait Cov07[-A <: AnyRef, +B] { }
+ trait Cov08[-A <: AnyRef, B] { }
+ trait Cov09[-A <: AnyRef, -B] { }
+
+ trait Cov11[+A <: AnyRef, +B <: List[_]] { }
+ trait Cov12[+A <: AnyRef, B <: List[_]] { }
+ trait Cov13[+A <: AnyRef, -B <: List[_]] { }
+ trait Cov14[ A <: AnyRef, +B <: List[_]] { }
+ trait Cov15[ A <: AnyRef, B <: List[_]] { }
+ trait Cov16[ A <: AnyRef, -B <: List[_]] { }
+ trait Cov17[-A <: AnyRef, +B <: List[_]] { }
+ trait Cov18[-A <: AnyRef, B <: List[_]] { }
+ trait Cov19[-A <: AnyRef, -B <: List[_]] { }
+
+ trait Cov21[+A, +B] { }
+ trait Cov22[+A, B] { }
+ trait Cov23[+A, -B] { }
+ trait Cov24[ A, +B] { }
+ trait Cov25[ A, B] { }
+ trait Cov26[ A, -B] { }
+ trait Cov27[-A, +B] { }
+ trait Cov28[-A, B] { }
+ trait Cov29[-A, -B] { }
+
+ trait Cov31[+A, +B, C <: ((A, B))] { }
+ trait Cov32[+A, B, C <: ((A, B))] { }
+ trait Cov33[+A, -B, C <: ((A, _))] { }
+ trait Cov34[ A, +B, C <: ((A, B))] { }
+ trait Cov35[ A, B, C <: ((A, B))] { }
+ trait Cov36[ A, -B, C <: ((A, _))] { }
+ trait Cov37[-A, +B, C <: ((_, B))] { }
+ trait Cov38[-A, B, C <: ((_, B))] { }
+ trait Cov39[-A, -B, C <: ((_, _))] { }
+
+ trait Cov41[+A >: Null, +B] { }
+ trait Cov42[+A >: Null, B] { }
+ trait Cov43[+A >: Null, -B] { }
+ trait Cov44[ A >: Null, +B] { }
+ trait Cov45[ A >: Null, B] { }
+ trait Cov46[ A >: Null, -B] { }
+ trait Cov47[-A >: Null, +B] { }
+ trait Cov48[-A >: Null, B] { }
+ trait Cov49[-A >: Null, -B] { }
+
+ trait Covariant[+A <: AnyRef, +B] { }
+ trait CovariantLike[+A <: AnyRef, +B <: List[A], +This <: CovariantLike[A, B, This] with Covariant[A, B]]
+
+ trait Contra[-A >: AnyRef, -B] { }
+ trait ContraLike[-A >: AnyRef, -B >: List[A]]
+}
+ """
+
+ def check(source: String, unit: global.CompilationUnit) = {
+ getRequiredModule("extest").moduleClass.info.decls.toList.filter(_.isType).map(_.initialize).sortBy(_.name.toString) foreach { clazz =>
+ afterTyper {
+ clazz.info
+ println(clazz.defString)
+ println(" " + classExistentialType(clazz) + "\n")
+ }
+ }
+ true
+ }
+}