summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala14
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala54
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala26
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala10
-rw-r--r--src/library/scala/collection/mutable/PriorityQueue.scala26
-rw-r--r--src/library/scala/collection/mutable/StackProxy.scala5
-rw-r--r--src/library/scala/concurrent/Future.scala102
-rw-r--r--src/library/scala/concurrent/Promise.scala14
-rw-r--r--src/library/scala/concurrent/impl/Future.scala2
-rw-r--r--src/library/scala/concurrent/impl/Promise.scala21
-rw-r--r--test/files/buildmanager/t2792/t2792.check3
-rw-r--r--test/files/jvm/actmig-PinS.check18
-rw-r--r--test/files/jvm/actmig-PinS.scala118
-rw-r--r--test/files/jvm/actmig-PinS_1.check18
-rw-r--r--test/files/jvm/actmig-PinS_1.scala130
-rw-r--r--test/files/jvm/actmig-PinS_2.check18
-rw-r--r--test/files/jvm/actmig-PinS_2.scala150
-rw-r--r--test/files/jvm/actmig-PinS_3.check19
-rw-r--r--test/files/jvm/actmig-PinS_3.scala159
-rw-r--r--test/files/jvm/actmig-hierarchy.check2
-rw-r--r--test/files/jvm/actmig-hierarchy.scala44
-rw-r--r--test/files/jvm/actmig-hierarchy_1.check2
-rw-r--r--test/files/jvm/actmig-hierarchy_1.scala41
-rw-r--r--test/files/jvm/actmig-instantiation.check8
-rw-r--r--test/files/jvm/actmig-instantiation.scala91
-rw-r--r--test/files/jvm/actmig-loop-react.check16
-rw-r--r--test/files/jvm/actmig-loop-react.scala170
-rw-r--r--test/files/jvm/actmig-public-methods.check6
-rw-r--r--test/files/jvm/actmig-public-methods.scala69
-rw-r--r--test/files/jvm/actmig-public-methods_1.check6
-rw-r--r--test/files/jvm/actmig-public-methods_1.scala88
-rw-r--r--test/files/jvm/actmig-react-receive.check16
-rw-r--r--test/files/jvm/actmig-react-receive.scala104
-rw-r--r--test/files/jvm/scala-concurrent-tck.scala121
-rw-r--r--test/files/neg/switch.flags1
-rw-r--r--test/files/neg/t5318.check5
-rw-r--r--test/files/neg/t5318.scala8
-rw-r--r--test/files/neg/t5318b.check5
-rw-r--r--test/files/neg/t5318b.scala8
-rw-r--r--test/files/neg/t5318c.check5
-rw-r--r--test/files/neg/t5318c.scala14
-rw-r--r--test/files/neg/t5821.check4
-rw-r--r--test/files/neg/t5821.scala8
-rw-r--r--test/files/neg/t639.check5
-rw-r--r--test/files/pos/t4911.flags1
-rw-r--r--test/files/pos/t4911.scala16
-rw-r--r--test/files/pos/t5041.scala9
-rw-r--r--test/files/run/t5428.check1
-rw-r--r--test/files/run/t5428.scala29
52 files changed, 414 insertions, 1413 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index c917ec9984..fb5b9b7169 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1468,20 +1468,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
refreshProgress
}
- /**
- * Attempt to locate a source file providing the given name as a top-level
- * definition in the given context, and add it to the run via compileLate
- * if found.
- */
- def compileSourceFor(context : analyzer.Context, name : Name) = false
-
- /**
- * Attempt to locate a source file providing the given name as a top-level
- * definition with the given prefix, and add it to the run via compileLate
- * if found.
- */
- def compileSourceFor(qual : Tree, name : Name) = false
-
/** Reset package class to state at typer (not sure what this
* is needed for?)
*/
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 81fe907a0c..99832d1327 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -223,8 +223,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
// unlike javaNameCache, reverseJavaName contains entries only for class symbols and their internal names.
val reverseJavaName = mutable.Map.empty[String, Symbol] ++= List(
- binarynme.RuntimeNothing.toString() -> NothingClass, // neither RuntimeNothingClass nor RuntimeNullClass belong to the co-domain of this map.
- binarynme.RuntimeNull.toString() -> NullClass
+ binarynme.RuntimeNothing.toString() -> RuntimeNothingClass, // RuntimeNothingClass is the bytecode-level return type of Scala methods with Nothing return-type.
+ binarynme.RuntimeNull.toString() -> RuntimeNullClass
)
private def mkFlags(args: Int*) = args.foldLeft(0)(_ | _)
@@ -587,7 +587,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
case None =>
reverseJavaName.put(internalName, trackedSym)
case Some(oldsym) =>
- assert(List(NothingClass, NullClass).contains(oldsym) || oldsym == trackedSym,
+ assert((oldsym == trackedSym) || List(RuntimeNothingClass, RuntimeNullClass).contains(oldsym), // NothingClass, NullClass,
"how can getCommonSuperclass() do its job if different class symbols get the same bytecode-level internal name.")
}
}
@@ -2542,7 +2542,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
} else if(kind.isRefOrArrayType) { // REFERENCE(_) | ARRAY(_)
val Success = success
val Failure = failure
- (cond, nextBlock) match {
+ // @unchecked because references aren't compared with GT, GE, LT, LE.
+ ((cond, nextBlock) : @unchecked) match {
case (EQ, Success) => jcode emitIFNONNULL labels(failure)
case (NE, Failure) => jcode emitIFNONNULL labels(success)
case (EQ, Failure) => jcode emitIFNULL labels(success)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index a671b8d6b5..217cadaab8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -346,7 +346,11 @@ trait Implicits {
case _ => tp
}
def stripped(tp: Type): Type = {
- deriveTypeWithWildcards(freeTypeParametersNoSkolems.collect(tp))(tp)
+ // `t.typeSymbol` returns the symbol of the normalized type. If that normalized type
+ // is a `PolyType`, the symbol of the result type is collected. This is precisely
+ // what we require for SI-5318.
+ val syms = for (t <- tp; if t.typeSymbol.isTypeParameter) yield t.typeSymbol
+ deriveTypeWithWildcards(syms.distinct)(tp)
}
def sum(xs: List[Int]) = (0 /: xs)(_ + _)
def complexity(tp: Type): Int = tp.normalize match {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index abe77ead9a..85c2aebfab 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -1088,7 +1088,7 @@ trait Infer {
*/
def inferConstructorInstance(tree: Tree, undetparams: List[Symbol], pt0: Type) {
val pt = widen(pt0)
- val ptparams = freeTypeParamsOfTerms.collect(pt)
+ val ptparams = freeTypeParamsOfTerms(pt)
val ctorTp = tree.tpe
val resTp = ctorTp.finalResultType
@@ -1322,8 +1322,8 @@ trait Infer {
def inferTypedPattern(tree0: Tree, pattp: Type, pt0: Type): Type = {
val pt = widen(pt0)
- val ptparams = freeTypeParamsOfTerms.collect(pt)
- val tpparams = freeTypeParamsOfTerms.collect(pattp)
+ val ptparams = freeTypeParamsOfTerms(pt)
+ val tpparams = freeTypeParamsOfTerms(pattp)
def ptMatchesPattp = pt matchesPattern pattp.widen
def pattpMatchesPt = pattp matchesPattern pt
@@ -1376,7 +1376,7 @@ trait Infer {
def inferModulePattern(pat: Tree, pt: Type) =
if (!(pat.tpe <:< pt)) {
- val ptparams = freeTypeParamsOfTerms.collect(pt)
+ val ptparams = freeTypeParamsOfTerms(pt)
debuglog("free type params (2) = " + ptparams)
val ptvars = ptparams map freshVar
val pt1 = pt.instantiateTypeParams(ptparams, ptvars)
@@ -1393,19 +1393,6 @@ trait Infer {
}
}
- abstract class SymCollector extends TypeCollector(List[Symbol]()) {
- protected def includeCondition(sym: Symbol): Boolean
-
- def traverse(tp: Type) {
- tp.normalize match {
- case TypeRef(_, sym, _) =>
- if (includeCondition(sym) && !result.contains(sym)) result = sym :: result
- case _ =>
- }
- mapOver(tp)
- }
- }
-
object approximateAbstracts extends TypeMap {
def apply(tp: Type): Type = tp.normalize match {
case TypeRef(pre, sym, _) if sym.isAbstractType => WildcardType
@@ -1413,31 +1400,30 @@ trait Infer {
}
}
- /** A traverser to collect type parameters referred to in a type
+ /** Collects type parameters referred to in a type.
*/
- object freeTypeParamsOfTerms extends SymCollector {
+ def freeTypeParamsOfTerms(tp: Type): List[Symbol] = {
// An inferred type which corresponds to an unknown type
// constructor creates a file/declaration order-dependent crasher
// situation, the behavior of which depends on the state at the
// time the typevar is created. Until we can deal with these
// properly, we can avoid it by ignoring type parameters which
// have type constructors amongst their bounds. See SI-4070.
- protected def includeCondition(sym: Symbol) = (
- sym.isAbstractType
- && sym.owner.isTerm
- && !sym.info.bounds.exists(_.typeParams.nonEmpty)
- )
- }
-
- /** A traverser to collect type parameters referred to in a type
- */
- object freeTypeParametersNoSkolems extends SymCollector {
- protected def includeCondition(sym: Symbol): Boolean =
- sym.isTypeParameter && sym.owner.isTerm
- }
+ def isFreeTypeParamOfTerm(sym: Symbol) = (
+ sym.isAbstractType
+ && sym.owner.isTerm
+ && !sym.info.bounds.exists(_.typeParams.nonEmpty)
+ )
- object typeRefs extends SymCollector {
- protected def includeCondition(sym: Symbol): Boolean = true
+ // Intentionally *not* using `Type#typeSymbol` here, which would normalize `tp`
+ // and collect symbols from the result type of any resulting `PolyType`s, which
+ // are not free type parameters of `tp`.
+ //
+ // Contrast with `isFreeTypeParamNoSkolem`.
+ val syms = tp collect {
+ case TypeRef(_, sym, _) if isFreeTypeParamOfTerm(sym) => sym
+ }
+ syms.distinct
}
/* -- Overload Resolution ---------------------------------------------- */
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index b4f42a5033..4eba665b93 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -473,12 +473,8 @@ trait Namers extends MethodSynthesis {
if (from != nme.WILDCARD && base != ErrorType) {
if (isValid(from)) {
- if (currentRun.compileSourceFor(expr, from)) {
- // side effecting, apparently
- typeSig(tree)
- }
// for Java code importing Scala objects
- else if (!nme.isModuleName(from) || isValid(nme.stripModuleSuffix(from))) {
+ if (!nme.isModuleName(from) || isValid(nme.stripModuleSuffix(from))) {
typer.TyperErrorGen.NotAMemberError(tree, expr, from)
typer.infer.setError(tree)
}
@@ -1306,14 +1302,18 @@ trait Namers extends MethodSynthesis {
if (expr1.symbol != null && expr1.symbol.isRootPackage)
RootImportError(tree)
- val newImport = treeCopy.Import(tree, expr1, selectors).asInstanceOf[Import]
- checkSelectors(newImport)
- transformed(tree) = newImport
- // copy symbol and type attributes back into old expression
- // so that the structure builder will find it.
- expr.symbol = expr1.symbol
- expr.tpe = expr1.tpe
- ImportType(expr1)
+ if (expr1.isErrorTyped)
+ ErrorType
+ else {
+ val newImport = treeCopy.Import(tree, expr1, selectors).asInstanceOf[Import]
+ checkSelectors(newImport)
+ transformed(tree) = newImport
+ // copy symbol and type attributes back into old expression
+ // so that the structure builder will find it.
+ expr.symbol = expr1.symbol
+ expr.tpe = expr1.tpe
+ ImportType(expr1)
+ }
}
val result =
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index 80d40011ad..4d66fb5617 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -1105,7 +1105,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
emitSwitch(scrut, scrutSym, casesNoSubstOnly, pt, matchFailGenOverride).getOrElse{
- if (requireSwitch) typer.context.unit.error(scrut.pos, "could not emit switch for @switch annotated match")
+ if (requireSwitch) typer.context.unit.warning(scrut.pos, "could not emit switch for @switch annotated match")
if (casesNoSubstOnly nonEmpty) {
// before optimizing, check casesNoSubstOnly for presence of a default case,
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 349bd1912b..75174ca494 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2549,9 +2549,11 @@ trait Typers extends Modes with Adaptations with Taggings {
else
stat match {
case imp @ Import(_, _) =>
- context = context.makeNewImport(imp)
imp.symbol.initialize
- typedImport(imp)
+ if (!imp.symbol.isError) {
+ context = context.makeNewImport(imp)
+ typedImport(imp)
+ } else EmptyTree
case _ =>
if (localTarget && !includesTargetPos(stat)) {
// skip typechecking of statements in a sequence where some other statement includes
@@ -4419,10 +4421,6 @@ trait Typers extends Modes with Adaptations with Taggings {
var cx = startingIdentContext
while (defSym == NoSymbol && cx != NoContext && (cx.scope ne null)) { // cx.scope eq null arises during FixInvalidSyms in Duplicators
- // !!! Shouldn't the argument to compileSourceFor be cx, not context?
- // I can't tell because those methods do nothing in the standard compiler,
- // presumably they are overridden in the IDE.
- currentRun.compileSourceFor(context.asInstanceOf[analyzer.Context], name)
pre = cx.enclClass.prefix
defEntry = cx.scope.lookupEntry(name)
if ((defEntry ne null) && qualifies(defEntry.sym)) {
diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala
index 12dee45bae..af55a01ed6 100644
--- a/src/library/scala/collection/mutable/PriorityQueue.scala
+++ b/src/library/scala/collection/mutable/PriorityQueue.scala
@@ -161,10 +161,13 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
*/
def clear(): Unit = { resarr.p_size0 = 1 }
- /** Returns an iterator which yields all the elements of the priority
- * queue in descending priority order.
+ /** Returns an iterator which yields all the elements.
*
- * @return an iterator over all elements sorted in descending order.
+ * Note: The order of elements returned is undefined.
+ * If you want to traverse the elements in priority queue
+ * order, use `clone().dequeueAll.iterator`.
+ *
+ * @return an iterator over all the elements.
*/
override def iterator: Iterator[A] = new AbstractIterator[A] {
private var i = 1
@@ -176,7 +179,6 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
}
}
-
/** Returns the reverse of this queue. The priority queue that gets
* returned will have an inversed ordering - if for some elements
* `x` and `y` the original queue's ordering
@@ -198,6 +200,13 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
revq
}
+ /** Returns an iterator which yields all the elements in the reverse order
+ * than that returned by the method `iterator`.
+ *
+ * Note: The order of elements returned is undefined.
+ *
+ * @return an iterator over all elements sorted in descending order.
+ */
def reverseIterator: Iterator[A] = new AbstractIterator[A] {
private var i = resarr.p_size0 - 1
def hasNext: Boolean = i >= 1
@@ -217,6 +226,8 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
throw new UnsupportedOperationException("unsuitable as hash key")
/** Returns a regular queue containing the same elements.
+ *
+ * Note: the order of elements is undefined.
*/
def toQueue: Queue[A] = new Queue[A] ++= this.iterator
@@ -225,6 +236,13 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
* @return the string representation of this queue.
*/
override def toString() = toList.mkString("PriorityQueue(", ", ", ")")
+
+ /** Converts this $coll to a list.
+ *
+ * Note: the order of elements is undefined.
+ *
+ * @return a list containing all elements of this $coll.
+ */
override def toList = this.iterator.toList
/** This method clones the priority queue.
diff --git a/src/library/scala/collection/mutable/StackProxy.scala b/src/library/scala/collection/mutable/StackProxy.scala
index 8884f03bbd..9eadfe4045 100644
--- a/src/library/scala/collection/mutable/StackProxy.scala
+++ b/src/library/scala/collection/mutable/StackProxy.scala
@@ -54,6 +54,11 @@ trait StackProxy[A] extends Stack[A] with Proxy {
this
}
+ override def push(elem: A): this.type = {
+ self.push(elem)
+ this
+ }
+
/** Returns the top element of the stack. This method will not remove
* the element from the stack. An error is signaled if there is no
* element on the stack.
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index 4df2bb63af..c42393eee2 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -82,9 +82,29 @@ import language.higherKinds
* {{{
* f flatMap { (x: Int) => g map { (y: Int) => x + y } }
* }}}
+ *
+ * @define callbackInContext
+ * The provided callback always runs in the provided implicit
+ *`ExecutionContext`, though there is no guarantee that the
+ * `execute()` method on the `ExecutionContext` will be called once
+ * per callback or that `execute()` will be called in the current
+ * thread. That is, the implementation may run multiple callbacks
+ * in a batch within a single `execute()` and it may run
+ * `execute()` either immediately or asynchronously.
*/
trait Future[+T] extends Awaitable[T] {
+ // The executor within the lexical scope
+ // of the Future trait. Note that this will
+ // (modulo bugs) _never_ execute a callback
+ // other than those below in this same file.
+ // As a nice side benefit, having this implicit
+ // here forces an ambiguity in those methods
+ // that also have an executor parameter, which
+ // keeps us from accidentally forgetting to use
+ // the executor parameter.
+ private implicit def internalExecutor: ExecutionContext = Future.InternalCallbackExecutor
+
/* Callbacks */
/** When this future is completed successfully (i.e. with a value),
@@ -95,11 +115,12 @@ trait Future[+T] extends Awaitable[T] {
* this will either be applied immediately or be scheduled asynchronously.
*
* $multipleCallbacks
+ * $callbackInContext
*/
- def onSuccess[U](pf: PartialFunction[T, U]): Unit = onComplete {
+ def onSuccess[U](pf: PartialFunction[T, U])(implicit executor: ExecutionContext): Unit = onComplete {
case Right(v) if pf isDefinedAt v => pf(v)
case _ =>
- }
+ }(executor)
/** When this future is completed with a failure (i.e. with a throwable),
* apply the provided callback to the throwable.
@@ -112,11 +133,12 @@ trait Future[+T] extends Awaitable[T] {
* Will not be called in case that the future is completed with a value.
*
* $multipleCallbacks
+ * $callbackInContext
*/
- def onFailure[U](callback: PartialFunction[Throwable, U]): Unit = onComplete {
+ def onFailure[U](callback: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Unit = onComplete {
case Left(t) if (isFutureThrowable(t) && callback.isDefinedAt(t)) => callback(t)
case _ =>
- }
+ }(executor)
/** When this future is completed, either through an exception, or a value,
* apply the provided function.
@@ -125,8 +147,9 @@ trait Future[+T] extends Awaitable[T] {
* this will either be applied immediately or be scheduled asynchronously.
*
* $multipleCallbacks
+ * $callbackInContext
*/
- def onComplete[U](func: Either[Throwable, T] => U): Unit
+ def onComplete[U](func: Either[Throwable, T] => U)(implicit executor: ExecutionContext): Unit
/* Miscellaneous */
@@ -182,10 +205,10 @@ trait Future[+T] extends Awaitable[T] {
*
* Will not be called if the future fails.
*/
- def foreach[U](f: T => U): Unit = onComplete {
+ def foreach[U](f: T => U)(implicit executor: ExecutionContext): Unit = onComplete {
case Right(r) => f(r)
case _ => // do nothing
- }
+ }(executor)
/** Creates a new future by applying the 's' function to the successful result of
* this future, or the 'f' function to the failed result. If there is any non-fatal
@@ -198,7 +221,7 @@ trait Future[+T] extends Awaitable[T] {
* the returned future
* @return a future that will be completed with the transformed value
*/
- def transform[S](s: T => S, f: Throwable => Throwable): Future[S] = {
+ def transform[S](s: T => S, f: Throwable => Throwable)(implicit executor: ExecutionContext): Future[S] = {
val p = Promise[S]()
onComplete {
@@ -211,7 +234,7 @@ trait Future[+T] extends Awaitable[T] {
} catch {
case NonFatal(t) => p failure t
}
- }
+ }(executor)
p.future
}
@@ -222,7 +245,7 @@ trait Future[+T] extends Awaitable[T] {
*
* $forComprehensionExamples
*/
- def map[S](f: T => S): Future[S] = { // transform(f, identity)
+ def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = { // transform(f, identity)
val p = Promise[S]()
onComplete {
@@ -235,7 +258,7 @@ trait Future[+T] extends Awaitable[T] {
} catch {
case NonFatal(t) => p failure t
}
- }
+ }(executor)
p.future
}
@@ -247,21 +270,21 @@ trait Future[+T] extends Awaitable[T] {
*
* $forComprehensionExamples
*/
- def flatMap[S](f: T => Future[S]): Future[S] = {
+ def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S] = {
val p = Promise[S]()
onComplete {
case l: Left[_, _] => p complete l.asInstanceOf[Left[Throwable, S]]
case Right(v) =>
try {
- f(v) onComplete {
+ f(v).onComplete({
case l: Left[_, _] => p complete l.asInstanceOf[Left[Throwable, S]]
case Right(v) => p success v
- }
+ })(internalExecutor)
} catch {
case NonFatal(t) => p failure t
}
- }
+ }(executor)
p.future
}
@@ -282,7 +305,7 @@ trait Future[+T] extends Awaitable[T] {
* await(h, 0) // throw a NoSuchElementException
* }}}
*/
- def filter(pred: T => Boolean): Future[T] = {
+ def filter(pred: T => Boolean)(implicit executor: ExecutionContext): Future[T] = {
val p = Promise[T]()
onComplete {
@@ -294,14 +317,14 @@ trait Future[+T] extends Awaitable[T] {
} catch {
case NonFatal(t) => p failure t
}
- }
+ }(executor)
p.future
}
/** Used by for-comprehensions.
*/
- final def withFilter(p: T => Boolean): Future[T] = filter(p)
+ final def withFilter(p: T => Boolean)(implicit executor: ExecutionContext): Future[T] = filter(p)(executor)
// final def withFilter(p: T => Boolean) = new FutureWithFilter[T](this, p)
// final class FutureWithFilter[+S](self: Future[S], p: S => Boolean) {
@@ -331,7 +354,7 @@ trait Future[+T] extends Awaitable[T] {
* await(h, 0) // throw a NoSuchElementException
* }}}
*/
- def collect[S](pf: PartialFunction[T, S]): Future[S] = {
+ def collect[S](pf: PartialFunction[T, S])(implicit executor: ExecutionContext): Future[S] = {
val p = Promise[S]()
onComplete {
@@ -343,7 +366,7 @@ trait Future[+T] extends Awaitable[T] {
} catch {
case NonFatal(t) => p failure t
}
- }
+ }(executor)
p.future
}
@@ -360,7 +383,7 @@ trait Future[+T] extends Awaitable[T] {
* future (6 / 2) recover { case e: ArithmeticException ⇒ 0 } // result: 3
* }}}
*/
- def recover[U >: T](pf: PartialFunction[Throwable, U]): Future[U] = {
+ def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] = {
val p = Promise[U]()
onComplete {
@@ -370,7 +393,7 @@ trait Future[+T] extends Awaitable[T] {
case NonFatal(t) => p failure t
}
case otherwise => p complete otherwise
- }
+ }(executor)
p.future
}
@@ -388,7 +411,7 @@ trait Future[+T] extends Awaitable[T] {
* future (6 / 0) recoverWith { case e: ArithmeticException => f } // result: Int.MaxValue
* }}}
*/
- def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]]): Future[U] = {
+ def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): Future[U] = {
val p = Promise[U]()
onComplete {
@@ -399,7 +422,7 @@ trait Future[+T] extends Awaitable[T] {
case NonFatal(t) => p failure t
}
case otherwise => p complete otherwise
- }
+ }(executor)
p.future
}
@@ -498,12 +521,12 @@ trait Future[+T] extends Awaitable[T] {
* }
* }}}
*/
- def andThen[U](pf: PartialFunction[Either[Throwable, T], U]): Future[T] = {
+ def andThen[U](pf: PartialFunction[Either[Throwable, T], U])(implicit executor: ExecutionContext): Future[T] = {
val p = Promise[T]()
onComplete {
case r => try if (pf isDefinedAt r) pf(r) finally p complete r
- }
+ }(executor)
p.future
}
@@ -656,6 +679,33 @@ object Future {
for (r <- fr; b <- fb) yield (r += b)
}.map(_.result)
+ // This is used to run callbacks which are internal
+ // to scala.concurrent; our own callbacks are only
+ // ever used to eventually run another callback,
+ // and that other callback will have its own
+ // executor because all callbacks come with
+ // an executor. Our own callbacks never block
+ // and have no "expected" exceptions.
+ // As a result, this executor can do nothing;
+ // some other executor will always come after
+ // it (and sometimes one will be before it),
+ // and those will be performing the "real"
+ // dispatch to code outside scala.concurrent.
+ // Because this exists, ExecutionContext.defaultExecutionContext
+ // isn't instantiated by Future internals, so
+ // if some code for some reason wants to avoid
+ // ever starting up the default context, it can do so
+ // by just not ever using it itself. scala.concurrent
+ // doesn't need to create defaultExecutionContext as
+ // a side effect.
+ private[concurrent] object InternalCallbackExecutor extends ExecutionContext {
+ def execute(runnable: Runnable): Unit =
+ runnable.run()
+ def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T =
+ throw new IllegalStateException("bug in scala.concurrent, called blocking() from internal callback")
+ def reportFailure(t: Throwable): Unit =
+ throw new IllegalStateException("problem in scala.concurrent internal callback", t)
+ }
}
diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala
index 2e9de4a0d0..578642966f 100644
--- a/src/library/scala/concurrent/Promise.scala
+++ b/src/library/scala/concurrent/Promise.scala
@@ -25,6 +25,11 @@ package scala.concurrent
*/
trait Promise[T] {
+ // used for internal callbacks defined in
+ // the lexical scope of this trait;
+ // _never_ for application callbacks.
+ private implicit def internalExecutor: ExecutionContext = Future.InternalCallbackExecutor
+
/** Future containing the value of this promise.
*/
def future: Future[T]
@@ -106,26 +111,23 @@ object Promise {
/** Creates a promise object which can be completed with a value.
*
* @tparam T the type of the value in the promise
- * @param executor the execution context on which the promise is created on
* @return the newly created `Promise` object
*/
- def apply[T]()(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.DefaultPromise[T]()
+ def apply[T](): Promise[T] = new impl.Promise.DefaultPromise[T]()
/** Creates an already completed Promise with the specified exception.
*
* @tparam T the type of the value in the promise
- * @param executor the execution context on which the promise is created on
* @return the newly created `Promise` object
*/
- def failed[T](exception: Throwable)(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.KeptPromise[T](Left(exception))
+ def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Left(exception))
/** Creates an already completed Promise with the specified result.
*
* @tparam T the type of the value in the promise
- * @param executor the execution context on which the promise is created on
* @return the newly created `Promise` object
*/
- def successful[T](result: T)(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.KeptPromise[T](Right(result))
+ def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Right(result))
}
diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala
index a54e81bd05..47534e398b 100644
--- a/src/library/scala/concurrent/impl/Future.scala
+++ b/src/library/scala/concurrent/impl/Future.scala
@@ -17,8 +17,6 @@ import scala.collection.mutable.Stack
private[concurrent] trait Future[+T] extends scala.concurrent.Future[T] with Awaitable[T] {
- implicit def executor: ExecutionContext
-
}
private[concurrent] object Future {
diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala
index 78053f5117..1d573ef818 100644
--- a/src/library/scala/concurrent/impl/Promise.scala
+++ b/src/library/scala/concurrent/impl/Promise.scala
@@ -42,7 +42,7 @@ object Promise {
/** Default promise implementation.
*/
- class DefaultPromise[T](implicit val executor: ExecutionContext) extends AbstractPromise with Promise[T] { self =>
+ class DefaultPromise[T] extends AbstractPromise with Promise[T] { self =>
updateState(null, Nil) // Start at "No callbacks" //FIXME switch to Unsafe instead of ARFU
protected final def tryAwait(atMost: Duration): Boolean = {
@@ -108,21 +108,26 @@ object Promise {
}) match {
case null => false
case cs if cs.isEmpty => true
- case cs => Future.dispatchFuture(executor, () => cs.foreach(f => notifyCompleted(f, resolved))); true
+ // this assumes that f(resolved) will go via dispatchFuture
+ // and notifyCompleted (see onComplete below)
+ case cs => cs.foreach(f => f(resolved)); true
}
}
- def onComplete[U](func: Either[Throwable, T] => U): Unit = {
+ def onComplete[U](func: Either[Throwable, T] => U)(implicit executor: ExecutionContext): Unit = {
+ val bound: Either[Throwable, T] => Unit = (either: Either[Throwable, T]) =>
+ Future.dispatchFuture(executor, () => notifyCompleted(func, either))
+
@tailrec //Tries to add the callback, if already completed, it dispatches the callback to be executed
def dispatchOrAddCallback(): Unit =
getState match {
- case r: Either[_, _] => Future.dispatchFuture(executor, () => notifyCompleted(func, r.asInstanceOf[Either[Throwable, T]]))
- case listeners: List[_] => if (updateState(listeners, func :: listeners)) () else dispatchOrAddCallback()
+ case r: Either[_, _] => bound(r.asInstanceOf[Either[Throwable, T]])
+ case listeners: List[_] => if (updateState(listeners, bound :: listeners)) () else dispatchOrAddCallback()
}
dispatchOrAddCallback()
}
- private final def notifyCompleted(func: Either[Throwable, T] => Any, result: Either[Throwable, T]) {
+ private final def notifyCompleted(func: Either[Throwable, T] => Any, result: Either[Throwable, T])(implicit executor: ExecutionContext) {
try {
func(result)
} catch {
@@ -135,7 +140,7 @@ object Promise {
*
* Useful in Future-composition when a value to contribute is already available.
*/
- final class KeptPromise[T](suppliedValue: Either[Throwable, T])(implicit val executor: ExecutionContext) extends Promise[T] {
+ final class KeptPromise[T](suppliedValue: Either[Throwable, T]) extends Promise[T] {
val value = Some(resolveEither(suppliedValue))
@@ -143,7 +148,7 @@ object Promise {
def tryComplete(value: Either[Throwable, T]): Boolean = false
- def onComplete[U](func: Either[Throwable, T] => U): Unit = {
+ def onComplete[U](func: Either[Throwable, T] => U)(implicit executor: ExecutionContext): Unit = {
val completedAs = value.get // Avoid closing over "this"
Future.dispatchFuture(executor, () => func(completedAs))
}
diff --git a/test/files/buildmanager/t2792/t2792.check b/test/files/buildmanager/t2792/t2792.check
index 68e14c6386..00a2b83469 100644
--- a/test/files/buildmanager/t2792/t2792.check
+++ b/test/files/buildmanager/t2792/t2792.check
@@ -9,3 +9,6 @@ compiling Set(A2.scala)
A2.scala:2: error: stable identifier required, but A.x found.
import A.x.y
^
+A2.scala:3: error: not found: value y
+ val z = y
+ ^
diff --git a/test/files/jvm/actmig-PinS.check b/test/files/jvm/actmig-PinS.check
deleted file mode 100644
index 97d1c5be02..0000000000
--- a/test/files/jvm/actmig-PinS.check
+++ /dev/null
@@ -1,18 +0,0 @@
-I'm acting!
-I'm acting!
-I'm acting!
-I'm acting!
-I'm acting!
-To be or not to be.
-To be or not to be.
-To be or not to be.
-To be or not to be.
-To be or not to be.
-That is the question.
-That is the question.
-That is the question.
-That is the question.
-That is the question.
-received message: hi there
-received message: 15
-Got an Int: 12
diff --git a/test/files/jvm/actmig-PinS.scala b/test/files/jvm/actmig-PinS.scala
deleted file mode 100644
index db5713dde4..0000000000
--- a/test/files/jvm/actmig-PinS.scala
+++ /dev/null
@@ -1,118 +0,0 @@
-import scala.actors._
-
-import scala.actors.Actor._
-
-/* PinS, Listing 32.1: A simple actor
- */
-object SillyActor extends Actor {
- def act() {
- for (i <- 1 to 5) {
- println("I'm acting!")
- //Thread.sleep(1000)
- Thread.sleep(10)
- }
- }
-}
-
-object SeriousActor extends Actor {
- def act() {
- for (i <- 1 to 5) {
- println("To be or not to be.")
- //Thread.sleep(1000)
- Thread.sleep(10)
- }
- }
-}
-
-/* PinS, Listing 32.3: An actor that calls react
- */
-object NameResolver extends Actor {
- import java.net.{InetAddress, UnknownHostException}
-
- def act() {
- react {
- case (name: String, actor: Actor) =>
- actor ! getIp(name)
- act()
- case "EXIT" =>
- println("Name resolver exiting.")
- // quit
- case msg =>
- println("Unhandled message: " + msg)
- act()
- }
- }
-
- def getIp(name: String): Option[InetAddress] = {
- try {
- Some(InetAddress.getByName(name))
- } catch {
- case _: UnknownHostException => None
- }
- }
-
-}
-
-object Test extends App {
-
- /* PinS, Listing 32.2: An actor that calls receive
- */
- def makeEchoActor(): Actor = actor {
- while (true) {
- receive {
- case 'stop =>
- exit()
- case msg =>
- println("received message: " + msg)
- }
- }
- }
-
- /* PinS, page 696
- */
- def makeIntActor(): Actor = actor {
- receive {
- case x: Int => // I only want Ints
- println("Got an Int: " + x)
- }
- }
-
-
- actor {
- self.trapExit = true
- self.link(SillyActor)
- SillyActor.start()
-
- react {
- case Exit(SillyActor, _) =>
- self.link(SeriousActor)
- SeriousActor.start()
- react {
- case Exit(SeriousActor, _) =>
- // PinS, page 694
- val seriousActor2 = actor {
- for (i <- 1 to 5)
- println("That is the question.")
- //Thread.sleep(1000)
- Thread.sleep(10)
- }
-
- Thread.sleep(200)
- val echoActor = makeEchoActor()
- self.link(echoActor)
- echoActor ! "hi there"
- echoActor ! 15
- echoActor ! 'stop
-
- react {
- case Exit(_, _) =>
- val intActor = makeIntActor()
- intActor ! "hello"
- intActor ! math.Pi
- // only the following send leads to output
- intActor ! 12
- }
- }
- }
- }
-}
diff --git a/test/files/jvm/actmig-PinS_1.check b/test/files/jvm/actmig-PinS_1.check
deleted file mode 100644
index 97d1c5be02..0000000000
--- a/test/files/jvm/actmig-PinS_1.check
+++ /dev/null
@@ -1,18 +0,0 @@
-I'm acting!
-I'm acting!
-I'm acting!
-I'm acting!
-I'm acting!
-To be or not to be.
-To be or not to be.
-To be or not to be.
-To be or not to be.
-To be or not to be.
-That is the question.
-That is the question.
-That is the question.
-That is the question.
-That is the question.
-received message: hi there
-received message: 15
-Got an Int: 12
diff --git a/test/files/jvm/actmig-PinS_1.scala b/test/files/jvm/actmig-PinS_1.scala
deleted file mode 100644
index d203526513..0000000000
--- a/test/files/jvm/actmig-PinS_1.scala
+++ /dev/null
@@ -1,130 +0,0 @@
-import scala.actors._
-
-object SillyActor {
- val ref = MigrationSystem.actorOf(Props(() => new SillyActor, "akka.actor.default-stash-dispatcher"))
-}
-
-/* PinS, Listing 32.1: A simple actor
- */
-class SillyActor extends Actor {
- def act() {
- for (i <- 1 to 5) {
- println("I'm acting!")
- Thread.sleep(10)
- }
- }
-}
-
-object SeriousActor {
- val ref = MigrationSystem.actorOf(Props(() => new SeriousActor, "akka.actor.default-stash-dispatcher"))
-}
-
-class SeriousActor extends Actor {
- def act() {
- for (i <- 1 to 5) {
- println("To be or not to be.")
- //Thread.sleep(1000)
- Thread.sleep(10)
- }
- }
-}
-
-/* PinS, Listing 32.3: An actor that calls react
- */
-object NameResolver extends Actor {
- import java.net.{ InetAddress, UnknownHostException }
-
- def act() {
- react {
- case (name: String, actor: Actor) =>
- actor ! getIp(name)
- act()
- case "EXIT" =>
- println("Name resolver exiting.")
- // quit
- case msg =>
- println("Unhandled message: " + msg)
- act()
- }
- }
-
- def getIp(name: String): Option[InetAddress] = {
- try {
- Some(InetAddress.getByName(name))
- } catch {
- case _: UnknownHostException => None
- }
- }
-
-}
-
-object Test extends App {
-
- /* PinS, Listing 32.2: An actor that calls receive
- */
- def makeEchoActor(): ActorRef = MigrationSystem.actorOf(Props(() => new Actor {
- def act() {
- while (true) {
- receive {
- case 'stop =>
- exit()
- case msg =>
- println("received message: " + msg)
- }
- }
- }
- }, "akka.actor.default-stash-dispatcher"))
-
- /* PinS, page 696
- */
- def makeIntActor(): ActorRef = MigrationSystem.actorOf(Props(() => new Actor {
- def act() {
- receive {
- case x: Int => // I only want Ints
- println("Got an Int: " + x)
- }
- }
- }, "akka.actor.default-stash-dispatcher"))
-
- MigrationSystem.actorOf(Props(() => new Actor {
- def act() {
- trapExit = true
- link(SillyActor.ref)
- react {
- case Exit(_: SillyActor, _) =>
- link(SeriousActor.ref)
- react {
- case Exit(_: SeriousActor, _) =>
- // PinS, page 694
- val seriousActor2 = MigrationSystem.actorOf(Props(() =>
- new Actor {
- def act() {
- for (i <- 1 to 5) {
- println("That is the question.")
- //Thread.sleep(1000)
- Thread.sleep(10)
- }
- }
- }
- , "akka.actor.default-stash-dispatcher"))
-
- Thread.sleep(200)
- val echoActor = makeEchoActor()
- link(echoActor)
- echoActor ! "hi there"
- echoActor ! 15
- echoActor ! 'stop
-
- react {
- case Exit(_, _) =>
- val intActor = makeIntActor()
- intActor ! "hello"
- intActor ! math.Pi
- // only the following send leads to output
- intActor ! 12
- }
- }
- }
- }
- }, "akka.actor.default-stash-dispatcher"))
-}
diff --git a/test/files/jvm/actmig-PinS_2.check b/test/files/jvm/actmig-PinS_2.check
deleted file mode 100644
index 97d1c5be02..0000000000
--- a/test/files/jvm/actmig-PinS_2.check
+++ /dev/null
@@ -1,18 +0,0 @@
-I'm acting!
-I'm acting!
-I'm acting!
-I'm acting!
-I'm acting!
-To be or not to be.
-To be or not to be.
-To be or not to be.
-To be or not to be.
-To be or not to be.
-That is the question.
-That is the question.
-That is the question.
-That is the question.
-That is the question.
-received message: hi there
-received message: 15
-Got an Int: 12
diff --git a/test/files/jvm/actmig-PinS_2.scala b/test/files/jvm/actmig-PinS_2.scala
deleted file mode 100644
index 9f52cca369..0000000000
--- a/test/files/jvm/actmig-PinS_2.scala
+++ /dev/null
@@ -1,150 +0,0 @@
-import scala.actors.{ MigrationSystem, StashingActor, ActorRef, Props, Exit }
-
-object SillyActor {
- val ref = MigrationSystem.actorOf(Props(() => new SillyActor, "default-stash-dispatcher"))
-}
-
-/* PinS, Listing 32.1: A simple actor
- */
-class SillyActor extends StashingActor {
-
- def receive = { case _ => println("Nop") }
-
- override def act() {
- for (i <- 1 to 5) {
- println("I'm acting!")
- Thread.sleep(10)
- }
- }
-}
-
-object SeriousActor {
- val ref = MigrationSystem.actorOf(Props(() => new SeriousActor, "default-stash-dispatcher"))
-}
-
-class SeriousActor extends StashingActor {
- def receive = { case _ => println("Nop") }
- override def act() {
- for (i <- 1 to 5) {
- println("To be or not to be.")
- Thread.sleep(10)
- }
- }
-}
-
-/* PinS, Listing 32.3: An actor that calls react
- */
-object NameResolver {
- val ref = MigrationSystem.actorOf(Props(() => new NameResolver, "default-stash-dispatcher"))
-}
-
-class NameResolver extends StashingActor {
- import java.net.{ InetAddress, UnknownHostException }
-
- def receive = { case _ => println("Nop") }
-
- override def act() {
- react {
- case (name: String, actor: ActorRef) =>
- actor ! getIp(name)
- act()
- case "EXIT" =>
- println("Name resolver exiting.")
- // quit
- case msg =>
- println("Unhandled message: " + msg)
- act()
- }
- }
-
- def getIp(name: String): Option[InetAddress] = {
- try {
- Some(InetAddress.getByName(name))
- } catch {
- case _: UnknownHostException => None
- }
- }
-
-}
-
-object Test extends App {
-
- /* PinS, Listing 32.2: An actor that calls receive
- */
- def makeEchoActor(): ActorRef = MigrationSystem.actorOf(Props(() =>
- new StashingActor {
- def receive = { case _ => println("Nop") }
-
- override def act() {
- loop {
- react {
- case 'stop =>
- exit()
- case msg =>
- println("received message: " + msg)
- }
- }
- }
- }, "default-stash-dispatcher"))
-
- /* PinS, page 696
- */
- def makeIntActor(): ActorRef = MigrationSystem.actorOf(Props(() =>new StashingActor {
-
- def receive = { case _ => println("Nop") }
-
- override def act() {
- react {
- case x: Int => // I only want Ints
- println("Got an Int: " + x)
- }
- }
- }, "default-stash-dispatcher"))
-
- MigrationSystem.actorOf(Props(() => new StashingActor {
-
- def receive = { case _ => println("Nop") }
-
- override def act() {
- trapExit = true
- link(SillyActor.ref)
- react {
- case Exit(_: SillyActor, _) =>
- link(SeriousActor.ref)
- react {
- case Exit(_: SeriousActor, _) =>
- // PinS, page 694
- val seriousActor2 = MigrationSystem.actorOf(Props(() =>{
- new StashingActor {
-
- def receive = { case _ => println("Nop") }
-
- override def act() {
- for (i <- 1 to 5) {
- println("That is the question.")
- Thread.sleep(10)
- }
- }
- }
- }, "default-stash-dispatcher"))
-
- Thread.sleep(200)
- val echoActor = makeEchoActor()
- link(echoActor)
- echoActor ! "hi there"
- echoActor ! 15
- echoActor ! 'stop
-
- react {
- case Exit(_, _) =>
- val intActor = makeIntActor()
- intActor ! "hello"
- intActor ! math.Pi
- // only the following send leads to output
- intActor ! 12
- }
- }
- }
- }
- }, "default-stash-dispatcher"))
-}
diff --git a/test/files/jvm/actmig-PinS_3.check b/test/files/jvm/actmig-PinS_3.check
deleted file mode 100644
index bdbdf8a692..0000000000
--- a/test/files/jvm/actmig-PinS_3.check
+++ /dev/null
@@ -1,19 +0,0 @@
-I'm acting!
-I'm acting!
-I'm acting!
-I'm acting!
-I'm acting!
-Post stop
-To be or not to be.
-To be or not to be.
-To be or not to be.
-To be or not to be.
-To be or not to be.
-That is the question.
-That is the question.
-That is the question.
-That is the question.
-That is the question.
-received message: hi there
-received message: 15
-Got an Int: 12
diff --git a/test/files/jvm/actmig-PinS_3.scala b/test/files/jvm/actmig-PinS_3.scala
deleted file mode 100644
index 047bf53c32..0000000000
--- a/test/files/jvm/actmig-PinS_3.scala
+++ /dev/null
@@ -1,159 +0,0 @@
-import scala.actors.{ MigrationSystem, StashingActor, ActorRef, Terminated, Props }
-
-object SillyActor {
- val ref = MigrationSystem.actorOf(Props(() => new SillyActor, "default-stash-dispatcher"))
-}
-
-/* PinS, Listing 32.1: A simple actor
- */
-class SillyActor extends StashingActor {
- def receive = { case _ => println("Why are you not dead"); context.stop(self) }
-
- override def preStart() {
- for (i <- 1 to 5) {
- println("I'm acting!")
- Thread.sleep(10)
- }
- context.stop(self)
- }
-
- override def postStop() {
- println("Post stop")
- }
-}
-
-object SeriousActor {
- val ref = MigrationSystem.actorOf(Props(() => new SeriousActor, "default-stash-dispatcher"))
-}
-
-class SeriousActor extends StashingActor {
- def receive = { case _ => println("Nop") }
- override def preStart() {
- for (i <- 1 to 5) {
- println("To be or not to be.")
- //Thread.sleep(1000)
- Thread.sleep(10)
- }
- context.stop(self)
- }
-}
-
-/* PinS, Listing 32.3: An actor that calls react
- */
-object NameResolver {
- val ref = MigrationSystem.actorOf(Props(() => new NameResolver, "default-stash-dispatcher"))
-}
-
-class NameResolver extends StashingActor {
- import java.net.{ InetAddress, UnknownHostException }
-
- def receive = {
- case (name: String, actor: ActorRef) =>
- actor ! getIp(name)
- case "EXIT" =>
- println("Name resolver exiting.")
- context.stop(self) // quit
- case msg =>
- println("Unhandled message: " + msg)
- }
-
- def getIp(name: String): Option[InetAddress] = {
- try {
- Some(InetAddress.getByName(name))
- } catch {
- case _: UnknownHostException => None
- }
- }
-
-}
-
-object Test extends App {
-
- /* PinS, Listing 32.2: An actor that calls receive
- */
- def makeEchoActor(): ActorRef = MigrationSystem.actorOf(Props(() => new StashingActor {
-
- def receive = { // how to handle receive
- case 'stop =>
- context.stop(self)
- case msg =>
- println("received message: " + msg)
- }
- }, "default-stash-dispatcher"))
-
- /* PinS, page 696
- */
- def makeIntActor(): ActorRef = MigrationSystem.actorOf(Props(() => new StashingActor {
-
- def receive = {
- case x: Int => // I only want Ints
- unstashAll()
- println("Got an Int: " + x)
- context.stop(self)
- case _ => stash()
- }
- }, "default-stash-dispatcher"))
-
- MigrationSystem.actorOf(Props(() => new StashingActor {
- val silly = SillyActor.ref
-
- override def preStart() {
- context.watch(SillyActor.ref)
- }
-
- def receive = {
- case Terminated(`silly`) =>
- unstashAll()
- val serious = SeriousActor.ref
- context.watch(SeriousActor.ref)
- context.become {
- case Terminated(`serious`) =>
- // PinS, page 694
- val seriousActor2 = MigrationSystem.actorOf(Props(() => {
- new StashingActor {
-
- def receive = { case _ => context.stop(self) }
-
- override def preStart() = {
- for (i <- 1 to 5) {
- println("That is the question.")
- //Thread.sleep(1000)
- Thread.sleep(10)
- }
- context.stop(self)
- }
- }
- }, "default-stash-dispatcher"))
-
- Thread.sleep(200)
- val echoActor = makeEchoActor()
- context.watch(echoActor)
- echoActor ! "hi there"
- echoActor ! 15
- echoActor ! 'stop
-
- context.become {
- case Terminated(_) =>
- unstashAll()
- val intActor = makeIntActor()
- intActor ! "hello"
- intActor ! math.Pi
- // only the following send leads to output
- intActor ! 12
- context.unbecome()
- context.unbecome()
- context.stop(self)
- case m =>
- println("Stash 1 " + m)
- stash(m)
- }
- case m =>
- println("Stash 2 " + m)
- stash(m)
- }
- case m =>
- println("Stash 3 " + m)
- stash(m)
- }
- }, "default-stash-dispatcher"))
-}
diff --git a/test/files/jvm/actmig-hierarchy.check b/test/files/jvm/actmig-hierarchy.check
deleted file mode 100644
index 317e9677c3..0000000000
--- a/test/files/jvm/actmig-hierarchy.check
+++ /dev/null
@@ -1,2 +0,0 @@
-hello
-hello
diff --git a/test/files/jvm/actmig-hierarchy.scala b/test/files/jvm/actmig-hierarchy.scala
deleted file mode 100644
index 7277329d85..0000000000
--- a/test/files/jvm/actmig-hierarchy.scala
+++ /dev/null
@@ -1,44 +0,0 @@
-import scala.actors._
-
-
-class ReactorActor extends Reactor[String] {
- def act() {
- var cond = true
- loopWhile(cond) {
- react {
- case x if x == "hello1" => println(x.dropRight(1))
- case "exit" => cond = false
- }
- }
- }
-}
-
-class ReplyActor extends ReplyReactor {
- def act() {
- var cond = true
- loopWhile(cond) {
- react {
- case "hello" => println("hello")
- case "exit" => cond = false;
- }
- }
- }
-}
-
-
-
-object Test {
-
- def main(args: Array[String]) {
- val reactorActor = new ReactorActor
- val replyActor = new ReplyActor
- reactorActor.start()
- replyActor.start()
-
- reactorActor ! "hello1"
- replyActor ! "hello"
-
- reactorActor ! "exit"
- replyActor ! "exit"
- }
-}
diff --git a/test/files/jvm/actmig-hierarchy_1.check b/test/files/jvm/actmig-hierarchy_1.check
deleted file mode 100644
index 317e9677c3..0000000000
--- a/test/files/jvm/actmig-hierarchy_1.check
+++ /dev/null
@@ -1,2 +0,0 @@
-hello
-hello
diff --git a/test/files/jvm/actmig-hierarchy_1.scala b/test/files/jvm/actmig-hierarchy_1.scala
deleted file mode 100644
index 559ebe7b11..0000000000
--- a/test/files/jvm/actmig-hierarchy_1.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-import scala.actors._
-
-class ReactorActor extends Actor {
- def act() {
- var cond = true
- loopWhile(cond) {
- react {
- case x: String if x == "hello1" => println(x.dropRight(1))
- case "exit" => cond = false
- }
- }
- }
-}
-
-class ReplyActor extends Actor {
- def act() {
- var cond = true
- loopWhile(cond) {
- react {
- case "hello" => println("hello")
- case "exit" => cond = false;
- }
- }
- }
-}
-
-object Test {
-
- def main(args: Array[String]) {
- val reactorActor = new ReactorActor
- val replyActor = new ReplyActor
- reactorActor.start()
- replyActor.start()
-
- reactorActor ! "hello1"
- replyActor ! "hello"
-
- reactorActor ! "exit"
- replyActor ! "exit"
- }
-}
diff --git a/test/files/jvm/actmig-instantiation.check b/test/files/jvm/actmig-instantiation.check
deleted file mode 100644
index 4c13d5c0a1..0000000000
--- a/test/files/jvm/actmig-instantiation.check
+++ /dev/null
@@ -1,8 +0,0 @@
-OK error: java.lang.RuntimeException: In order to create StashingActor one must use actorOf.
-OK error: java.lang.RuntimeException: Only one actor can be created per actorOf call.
-0
-100
-200
-300
-400
-500
diff --git a/test/files/jvm/actmig-instantiation.scala b/test/files/jvm/actmig-instantiation.scala
deleted file mode 100644
index 4170dbd3ad..0000000000
--- a/test/files/jvm/actmig-instantiation.scala
+++ /dev/null
@@ -1,91 +0,0 @@
-import scala.actors.MigrationSystem._
-import scala.actors.Actor._
-import scala.actors.{ Actor, StashingActor, ActorRef, Props, MigrationSystem, PoisonPill }
-import java.util.concurrent.{ TimeUnit, CountDownLatch }
-import scala.collection.mutable.ArrayBuffer
-
-class TestStashingActor extends StashingActor {
-
- def receive = { case v: Int => Test.append(v); Test.latch.countDown() }
-
-}
-
-object Test {
- val NUMBER_OF_TESTS = 5
-
- // used for sorting non-deterministic output
- val buff = ArrayBuffer[Int](0)
- val latch = new CountDownLatch(NUMBER_OF_TESTS)
- val toStop = ArrayBuffer[ActorRef]()
-
- def append(v: Int) = synchronized {
- buff += v
- }
-
- def main(args: Array[String]) = {
- // plain scala actor
- val a1 = actor {
- react { case v: Int => Test.append(v); Test.latch.countDown() }
- }
- a1 ! 100
-
- // simple instantiation
- val a2 = MigrationSystem.actorOf(Props(() => new TestStashingActor, "akka.actor.default-stash-dispatcher"))
- a2 ! 200
- toStop += a2
-
- // actor of with scala actor
- val a3 = actorOf(Props(() => actor {
- react { case v: Int => Test.append(v); Test.latch.countDown() }
- }, "akka.actor.default-stash-dispatcher"))
- a3 ! 300
-
- // using the manifest
- val a4 = actorOf(Props(() => new TestStashingActor, "akka.actor.default-stash-dispatcher"))
- a4 ! 400
- toStop += a4
-
- // deterministic part of a test
- // creation without actorOf
- try {
- val a3 = new TestStashingActor
- a3 ! -1
- } catch {
- case e => println("OK error: " + e)
- }
-
- // actorOf double creation
- try {
- val a3 = actorOf(Props(() => {
- new TestStashingActor
- new TestStashingActor
- }, "akka.actor.default-stash-dispatcher"))
- a3 ! -1
- } catch {
- case e => println("OK error: " + e)
- }
-
- // actorOf nesting
- try {
- val a5 = actorOf(Props(() => {
- val a6 = actorOf(Props(() => new TestStashingActor, "akka.actor.default-stash-dispatcher"))
- toStop += a6
- new TestStashingActor
- }, "akka.actor.default-stash-dispatcher"))
-
- a5 ! 500
- toStop += a5
- } catch {
- case e => println("Should not throw an exception: " + e)
- }
-
- // output
- latch.await(200, TimeUnit.MILLISECONDS)
- if (latch.getCount() > 0) {
- println("Error: Tasks have not finished!!!")
- }
-
- buff.sorted.foreach(println)
- toStop.foreach(_ ! PoisonPill)
- }
-}
diff --git a/test/files/jvm/actmig-loop-react.check b/test/files/jvm/actmig-loop-react.check
deleted file mode 100644
index 7b955aa9b9..0000000000
--- a/test/files/jvm/actmig-loop-react.check
+++ /dev/null
@@ -1,16 +0,0 @@
-do task
-do task
-do task
-do task
-working
-scala got exception
-working
-akka got exception
-do task 1
-do string I am a String
-do task 42
-after react
-Terminated
-do task 1
-do string I am a String
-do task 42
diff --git a/test/files/jvm/actmig-loop-react.scala b/test/files/jvm/actmig-loop-react.scala
deleted file mode 100644
index 8452f9766a..0000000000
--- a/test/files/jvm/actmig-loop-react.scala
+++ /dev/null
@@ -1,170 +0,0 @@
-import scala.actors.MigrationSystem._
-import scala.actors.Actor._
-import scala.actors.{ Actor, StashingActor, ActorRef, Props, MigrationSystem, PoisonPill }
-import java.util.concurrent.{ TimeUnit, CountDownLatch }
-import scala.collection.mutable.ArrayBuffer
-
-object Test {
-
- def testLoopWithConditionReact() = {
- // Snippet showing composition of receives
- // Loop with Condition Snippet - before
- val myActor = actor {
- var c = true
- loopWhile(c) {
- react {
- case x: Int =>
- // do task
- println("do task")
- if (x == 42) c = false
- }
- }
- }
-
- myActor.start()
- myActor ! 1
- myActor ! 42
-
- // Loop with Condition Snippet - migrated
- val myAkkaActor = MigrationSystem.actorOf(Props(() => new StashingActor {
-
- def receive = {
- case x: Int =>
- // do task
- println("do task")
- if (x == 42) context.stop(self)
- }
- }, "default-stashing-dispatcher"))
- myAkkaActor ! 1
- myAkkaActor ! 42
- }
-
- def testNestedReact() = {
- // Snippet showing composition of receives
- // Loop with Condition Snippet - before
- val myActor = actor {
- var c = true
- loopWhile(c) {
- react {
- case x: Int =>
- // do task
- println("do task " + x)
- if (x == 42) c = false
- else
- react {
- case y: String =>
- println("do string " + y)
- }
- println("after react")
- }
- }
- }
- myActor.start()
-
- myActor ! 1
- myActor ! "I am a String"
- myActor ! 42
-
- Thread.sleep(100)
- println(myActor.getState)
-
- // Loop with Condition Snippet - migrated
- val myAkkaActor = MigrationSystem.actorOf(Props(() => new StashingActor {
-
- def receive = {
- case x: Int =>
- // do task
- println("do task " + x)
- if (x == 42)
- context.stop(self)
- else
- context.become(({
- case y: String =>
- println("do string " + y)
- }: Receive).andThen(x => {
- unstashAll()
- context.unbecome()
- }).orElse { case x => stash() })
- }
- }, "default-stashing-dispatcher"))
-
- myAkkaActor ! 1
- myAkkaActor ! "I am a String"
- myAkkaActor ! 42
-
- }
-
- def exceptionHandling() = {
- // Stashing actor with act and exception handler
- val myActor = MigrationSystem.actorOf(Props(() => new StashingActor {
-
- def receive = { case _ => println("Dummy method.") }
- override def act() = {
- loop {
- react {
- case "fail" =>
- throw new Exception("failed")
- case "work" =>
- println("working")
- case "die" =>
- exit()
- }
- }
- }
-
- override def exceptionHandler = {
- case x: Exception => println("scala got exception")
- }
-
- }, "default-stashing-dispatcher"))
-
- myActor ! "work"
- myActor ! "fail"
- myActor ! "die"
-
- Thread.sleep(100)
- // Stashing actor in Akka style
- val myAkkaActor = MigrationSystem.actorOf(Props(() => new StashingActor {
- def receive = PFCatch({
- case "fail" =>
- throw new Exception("failed")
- case "work" =>
- println("working")
- case "die" =>
- context.stop(self)
- }, { case x: Exception => println("akka got exception") })
- }, "default-stashing-dispatcher"))
-
- myAkkaActor ! "work"
- myAkkaActor ! "fail"
- myAkkaActor ! "die"
- }
-
- def main(args: Array[String]) = {
- testLoopWithConditionReact()
- Thread.sleep(100)
- exceptionHandling()
- Thread.sleep(100)
- testNestedReact()
- }
-
-}
-
-// As per Jim Mcbeath blog (http://jim-mcbeath.blogspot.com/2008/07/actor-exceptions.html)
-class PFCatch(f: PartialFunction[Any, Unit], handler: PartialFunction[Exception, Unit])
- extends PartialFunction[Any, Unit] {
-
- def apply(x: Any) = {
- try {
- f(x)
- } catch {
- case e: Exception if handler.isDefinedAt(e) => handler(e)
- }
- }
-
- def isDefinedAt(x: Any) = f.isDefinedAt(x)
-}
-
-object PFCatch {
- def apply(f: PartialFunction[Any, Unit], handler: PartialFunction[Exception, Unit]) = new PFCatch(f, handler)
-}
diff --git a/test/files/jvm/actmig-public-methods.check b/test/files/jvm/actmig-public-methods.check
deleted file mode 100644
index bb6530c926..0000000000
--- a/test/files/jvm/actmig-public-methods.check
+++ /dev/null
@@ -1,6 +0,0 @@
-None
-Some(bang qmark after 1)
-bang
-bang qmark after 0
-bang qmark in future after 0
-typed bang qmark in future after 0
diff --git a/test/files/jvm/actmig-public-methods.scala b/test/files/jvm/actmig-public-methods.scala
deleted file mode 100644
index c4c8560122..0000000000
--- a/test/files/jvm/actmig-public-methods.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-import scala.collection.mutable.ArrayBuffer
-import scala.actors.Actor._
-import scala.actors._
-import scala.actors.MigrationSystem
-import scala.util.continuations._
-import java.util.concurrent.{ TimeUnit, CountDownLatch }
-
-object Test {
- val NUMBER_OF_TESTS = 6
-
- // used for sorting non-deterministic output
- val buff = ArrayBuffer[String]()
- val latch = new CountDownLatch(NUMBER_OF_TESTS)
- val toStop = ArrayBuffer[Actor]()
-
- def append(v: String) = synchronized {
- buff += v
- }
-
- def main(args: Array[String]) = {
-
- val respActor = actor {
- loop {
- react {
- case (x: String, time: Long) =>
- Thread.sleep(time)
- reply(x + " after " + time)
- case str: String =>
- append(str)
- latch.countDown()
- case _ => exit()
- }
- }
- }
-
- toStop += respActor
-
- respActor ! ("bang")
-
- val res1 = respActor !? (("bang qmark", 0L))
- append(res1.toString)
- latch.countDown()
-
- val res2 = respActor !? (200, ("bang qmark", 1L))
- append(res2.toString)
- latch.countDown()
-
- val res21 = respActor !? (1, ("bang qmark", 200L))
- append(res21.toString)
- latch.countDown()
-
- val fut1 = respActor !! (("bang qmark in future", 0L))
- append(fut1().toString())
- latch.countDown()
-
- val fut2 = respActor !! (("typed bang qmark in future", 0L), { case x: String => x })
- append(fut2())
- latch.countDown()
-
- // output
- latch.await(10, TimeUnit.MILLISECONDS)
- if (latch.getCount() > 0) {
- println("Error: Tasks have not finished!!!")
- }
-
- buff.sorted.foreach(println)
- toStop.foreach(_ ! 'stop)
- }
-}
diff --git a/test/files/jvm/actmig-public-methods_1.check b/test/files/jvm/actmig-public-methods_1.check
deleted file mode 100644
index bb6530c926..0000000000
--- a/test/files/jvm/actmig-public-methods_1.check
+++ /dev/null
@@ -1,6 +0,0 @@
-None
-Some(bang qmark after 1)
-bang
-bang qmark after 0
-bang qmark in future after 0
-typed bang qmark in future after 0
diff --git a/test/files/jvm/actmig-public-methods_1.scala b/test/files/jvm/actmig-public-methods_1.scala
deleted file mode 100644
index 41798c4c37..0000000000
--- a/test/files/jvm/actmig-public-methods_1.scala
+++ /dev/null
@@ -1,88 +0,0 @@
-import scala.collection.mutable.ArrayBuffer
-import scala.actors.Actor._
-import scala.actors._
-import scala.util._
-import java.util.concurrent.{ TimeUnit, CountDownLatch }
-import scala.concurrent.util.Duration
-import scala.actors.pattern._
-
-object Test {
- val NUMBER_OF_TESTS = 6
-
- // used for sorting non-deterministic output
- val buff = ArrayBuffer[String]()
- val latch = new CountDownLatch(NUMBER_OF_TESTS)
- val toStop = ArrayBuffer[ActorRef]()
-
- def append(v: String) = synchronized {
- buff += v
- }
-
- def main(args: Array[String]) = {
-
- val respActor = MigrationSystem.actorOf(Props(() => actor {
- loop {
- react {
- case (x: String, time: Long) =>
- Thread.sleep(time)
- reply(x + " after " + time)
- case str: String =>
- append(str)
- latch.countDown()
- case x =>
- exit()
- }
- }
- }, "akka.actor.default-stash-dispatcher"))
-
- toStop += respActor
-
- respActor ! "bang"
-
- implicit val timeout = Timeout(Duration(200, TimeUnit.MILLISECONDS))
- val msg = ("bang qmark", 0L)
- val res1 = respActor.?(msg)(Timeout(Duration.Inf))
- append(res1().toString)
- latch.countDown()
-
- val msg1 = ("bang qmark", 1L)
- val res2 = respActor.?(msg1)(Timeout(Duration(200, TimeUnit.MILLISECONDS)))
- append((res2() match {
- case x: AskTimeoutException => None
- case v => Some(v)
- }).toString)
- latch.countDown()
-
- // this one should time out
- val msg11 = ("bang qmark", 200L)
- val res21 = respActor.?(msg11)(Timeout(Duration(1, TimeUnit.MILLISECONDS)))
- append((res21() match {
- case x: AskTimeoutException => None
- case v => Some(v)
- }).toString)
- latch.countDown()
-
- val msg2 = ("bang qmark in future", 0L)
- val fut1 = respActor.?(msg2)(Duration.Inf)
- append(fut1().toString())
- latch.countDown()
-
- val handler: PartialFunction[Any, String] = {
- case x: String => x.toString
- }
-
- val msg3 = ("typed bang qmark in future", 0L)
- val fut2 = (respActor.?(msg3)(Duration.Inf))
- append(Futures.future { handler.apply(fut2()) }().toString)
- latch.countDown()
-
- // output
- latch.await(10, TimeUnit.MILLISECONDS)
- if (latch.getCount() > 0) {
- println("Error: Tasks have not finished!!!")
- }
-
- buff.sorted.foreach(println)
- toStop.foreach(_ ! PoisonPill)
- }
-}
diff --git a/test/files/jvm/actmig-react-receive.check b/test/files/jvm/actmig-react-receive.check
deleted file mode 100644
index cc2a426e68..0000000000
--- a/test/files/jvm/actmig-react-receive.check
+++ /dev/null
@@ -1,16 +0,0 @@
-do before
-do task
-do after
-do before
-do task
-do after
-do before
-do task
-do in between
-do string
-do after
-do before
-do task
-do in between
-do string
-do after
diff --git a/test/files/jvm/actmig-react-receive.scala b/test/files/jvm/actmig-react-receive.scala
deleted file mode 100644
index fbc10a8d52..0000000000
--- a/test/files/jvm/actmig-react-receive.scala
+++ /dev/null
@@ -1,104 +0,0 @@
-import scala.actors.MigrationSystem._
-import scala.actors.Actor._
-import scala.actors.{ Actor, StashingActor, ActorRef, Props, MigrationSystem, PoisonPill }
-import java.util.concurrent.{ TimeUnit, CountDownLatch }
-import scala.collection.mutable.ArrayBuffer
-
-object Test {
-
- def testComposition() = {
- // Snippet showing composition of receives
- // React Snippet - before
- val myActor = actor {
- // do before
- println("do before")
- receive {
- case x: Int =>
- // do task
- println("do task")
- }
- println("do in between")
- receive {
- case x: String =>
- // do string now
- println("do string")
- }
- println("do after")
- }
- myActor.start()
- myActor ! 1
- myActor ! "1"
- Thread.sleep(200)
- // React Snippet - migrated
- val myAkkaActor = MigrationSystem.actorOf(Props(() => new StashingActor {
- override def preStart() = {
- println("do before")
- }
-
- def receive = ({
- case x: Int =>
- // do task
- println("do task")
- }: Receive) andThen { v =>
- context.become {
- case x: String =>
- //do string
- println("do string")
- context.stop(self)
- }
- println("do in between")
- }
-
- override def postStop() = {
- println("do after")
- }
-
- }, "default-stashing-dispatcher"))
- myAkkaActor ! 1
- myAkkaActor ! "1"
- Thread.sleep(200)
- }
-
- def main(args: Array[String]) = {
- // React Snippet - before
- val myActor = actor {
- // do before
- println("do before")
- receive {
- case x: Int =>
- // do task
- println("do task")
- }
- println("do after")
- }
- myActor.start()
- myActor ! 1
-
- Thread.sleep(200)
-
- // React Snippet - migrated
- val myAkkaActor = MigrationSystem.actorOf(Props(() => new StashingActor {
- override def preStart() = {
- println("do before")
- }
-
- def receive = {
- case x: Int =>
- // do task
- println("do task")
- context.stop(self)
- }
-
- override def postStop() = {
- println("do after")
- }
-
- }, "default-stashing-dispatcher"))
- myAkkaActor ! 1
-
- Thread.sleep(200)
- // Starting composition test
- testComposition()
-
- }
-}
diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala
index 86655ad89c..012460147a 100644
--- a/test/files/jvm/scala-concurrent-tck.scala
+++ b/test/files/jvm/scala-concurrent-tck.scala
@@ -808,6 +808,126 @@ trait TryEitherExtractor extends TestBase {
testLeftMatch()
}
+trait CustomExecutionContext extends TestBase {
+ import scala.concurrent.{ ExecutionContext, Awaitable }
+
+ def defaultEC = ExecutionContext.defaultExecutionContext
+
+ val inEC = new java.lang.ThreadLocal[Int]() {
+ override def initialValue = 0
+ }
+
+ def enterEC() = inEC.set(inEC.get + 1)
+ def leaveEC() = inEC.set(inEC.get - 1)
+ def assertEC() = assert(inEC.get > 0)
+ def assertNoEC() = assert(inEC.get == 0)
+
+ class CountingExecutionContext extends ExecutionContext {
+ val _count = new java.util.concurrent.atomic.AtomicInteger(0)
+ def count = _count.get
+
+ def delegate = ExecutionContext.defaultExecutionContext
+
+ override def execute(runnable: Runnable) = {
+ _count.incrementAndGet()
+ val wrapper = new Runnable() {
+ override def run() = {
+ enterEC()
+ try {
+ runnable.run()
+ } finally {
+ leaveEC()
+ }
+ }
+ }
+ delegate.execute(wrapper)
+ }
+
+ override def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T =
+ delegate.internalBlockingCall(awaitable, atMost)
+
+ override def reportFailure(t: Throwable): Unit = {
+ System.err.println("Failure: " + t.getClass.getSimpleName + ": " + t.getMessage)
+ delegate.reportFailure(t)
+ }
+ }
+
+ def countExecs(block: (ExecutionContext) => Unit): Int = {
+ val context = new CountingExecutionContext()
+ block(context)
+ context.count
+ }
+
+ def testOnSuccessCustomEC(): Unit = {
+ val count = countExecs { implicit ec =>
+ once { done =>
+ val f = future({ assertNoEC() })(defaultEC)
+ f onSuccess {
+ case _ =>
+ assertEC()
+ done()
+ }
+ assertNoEC()
+ }
+ }
+
+ // should be onSuccess, but not future body
+ assert(count == 1)
+ }
+
+ def testKeptPromiseCustomEC(): Unit = {
+ val count = countExecs { implicit ec =>
+ once { done =>
+ val f = Promise.successful(10).future
+ f onSuccess {
+ case _ =>
+ assertEC()
+ done()
+ }
+ }
+ }
+
+ // should be onSuccess called once in proper EC
+ assert(count == 1)
+ }
+
+ def testCallbackChainCustomEC(): Unit = {
+ val count = countExecs { implicit ec =>
+ once { done =>
+ assertNoEC()
+ val addOne = { x: Int => assertEC(); x + 1 }
+ val f = Promise.successful(10).future
+ f.map(addOne).filter { x =>
+ assertEC()
+ x == 11
+ } flatMap { x =>
+ Promise.successful(x + 1).future.map(addOne).map(addOne)
+ } onComplete {
+ case Left(t) =>
+ try {
+ throw new AssertionError("error in test: " + t.getMessage, t)
+ } finally {
+ done()
+ }
+ case Right(x) =>
+ assertEC()
+ assert(x == 14)
+ done()
+ }
+ assertNoEC()
+ }
+ }
+
+ // the count is not defined (other than >=1)
+ // due to the batching optimizations.
+ assert(count >= 1)
+ }
+
+ testOnSuccessCustomEC()
+ testKeptPromiseCustomEC()
+ testCallbackChainCustomEC()
+}
+
object Test
extends App
with FutureCallbacks
@@ -816,6 +936,7 @@ with FutureProjections
with Promises
with Exceptions
with TryEitherExtractor
+with CustomExecutionContext
{
System.exit(0)
}
diff --git a/test/files/neg/switch.flags b/test/files/neg/switch.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/switch.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t5318.check b/test/files/neg/t5318.check
new file mode 100644
index 0000000000..d6a3a57935
--- /dev/null
+++ b/test/files/neg/t5318.check
@@ -0,0 +1,5 @@
+t5318.scala:7: error: diverging implicit expansion for type CompilerHang.this.TC[F]
+starting with method tc in class CompilerHang
+ breakage // type checker doesn't terminate, should report inference failure
+ ^
+one error found
diff --git a/test/files/neg/t5318.scala b/test/files/neg/t5318.scala
new file mode 100644
index 0000000000..8009c66e6b
--- /dev/null
+++ b/test/files/neg/t5318.scala
@@ -0,0 +1,8 @@
+class CompilerHang {
+ trait TC[M[_]]
+ trait S[A]
+
+ implicit def tc[M[_]](implicit M0: TC[M]): TC[S] = null
+ def breakage[F[_] : TC] = 0
+ breakage // type checker doesn't terminate, should report inference failure
+} \ No newline at end of file
diff --git a/test/files/neg/t5318b.check b/test/files/neg/t5318b.check
new file mode 100644
index 0000000000..47a10d6733
--- /dev/null
+++ b/test/files/neg/t5318b.check
@@ -0,0 +1,5 @@
+t5318b.scala:7: error: diverging implicit expansion for type DivergingImplicitReported.this.TC[F]
+starting with method tc in class DivergingImplicitReported
+ breakage // correct: diverging implicit expansion
+ ^
+one error found \ No newline at end of file
diff --git a/test/files/neg/t5318b.scala b/test/files/neg/t5318b.scala
new file mode 100644
index 0000000000..123f8b4e04
--- /dev/null
+++ b/test/files/neg/t5318b.scala
@@ -0,0 +1,8 @@
+class DivergingImplicitReported {
+ trait TC[M]
+ trait S
+
+ implicit def tc[M](implicit M0: TC[M]): TC[S] = null
+ def breakage[F: TC] = 0
+ breakage // correct: diverging implicit expansion
+} \ No newline at end of file
diff --git a/test/files/neg/t5318c.check b/test/files/neg/t5318c.check
new file mode 100644
index 0000000000..594539be69
--- /dev/null
+++ b/test/files/neg/t5318c.check
@@ -0,0 +1,5 @@
+t5318c.scala:13: error: diverging implicit expansion for type CompilerHang.this.TC[F]
+starting with method tc in class CompilerHang
+ breakage // type checker doesn't terminate, should report inference failure
+ ^
+one error found
diff --git a/test/files/neg/t5318c.scala b/test/files/neg/t5318c.scala
new file mode 100644
index 0000000000..477a9874ad
--- /dev/null
+++ b/test/files/neg/t5318c.scala
@@ -0,0 +1,14 @@
+class CompilerHang {
+ trait TC[M[_]]
+ trait S[A]
+
+ class C[M[_]] {
+ type TCM = TC[M]
+ }
+
+ // A nefarious implicit, to motivate the removal of `&& sym.owner.isTerm` from
+ // `isFreeTypeParamNoSkolem`.
+ implicit def tc[x[_], CC[x[_]] <: C[x]](implicit M0: CC[x]#TCM): CC[x]#TCM = null
+ def breakage[F[_] : TC] = 0
+ breakage // type checker doesn't terminate, should report inference failure
+}
diff --git a/test/files/neg/t5821.check b/test/files/neg/t5821.check
new file mode 100644
index 0000000000..f9c00604bc
--- /dev/null
+++ b/test/files/neg/t5821.check
@@ -0,0 +1,4 @@
+t5821.scala:1: error: not found: object SthImportant
+import SthImportant._
+ ^
+one error found
diff --git a/test/files/neg/t5821.scala b/test/files/neg/t5821.scala
new file mode 100644
index 0000000000..4af0a2bf7f
--- /dev/null
+++ b/test/files/neg/t5821.scala
@@ -0,0 +1,8 @@
+import SthImportant._
+
+class Bar
+
+class Foo2 {
+ type Sth = Array[Bar]
+ def foo(xs: Sth): Bar = if ((xs eq null) || (xs.length == 0)) null else xs(0)
+}
diff --git a/test/files/neg/t639.check b/test/files/neg/t639.check
index 3b53da0515..6d41d872de 100644
--- a/test/files/neg/t639.check
+++ b/test/files/neg/t639.check
@@ -1,4 +1,7 @@
t639.scala:3: error: not found: object a
import a._
^
-one error found
+t639.scala:5: error: not found: type B
+@B
+ ^
+two errors found
diff --git a/test/files/pos/t4911.flags b/test/files/pos/t4911.flags
new file mode 100644
index 0000000000..779916d58f
--- /dev/null
+++ b/test/files/pos/t4911.flags
@@ -0,0 +1 @@
+-unchecked -Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t4911.scala b/test/files/pos/t4911.scala
new file mode 100644
index 0000000000..66c867a37f
--- /dev/null
+++ b/test/files/pos/t4911.scala
@@ -0,0 +1,16 @@
+import language._
+
+object Test {
+ class Foo[T](val x: T) ; object Foo { def unapply[T](x: Foo[T]) = Some(x.x) }
+ def f1[T](x: Foo[T]) = x match { case Foo(y) => y }
+ def f2[M[_], T](x: M[T]) = x match { case Foo(y) => y }
+
+ case class Bar[T](x: T)
+ def f3[T](x: Bar[T]) = x match { case Bar(y) => y }
+ def f4[M[_], T](x: M[T]) = x match { case Bar(y) => y }
+}
+//
+// ./b.scala:4: warning: non variable type-argument T in type pattern Test.Foo[T] is unchecked since it is eliminated by erasure
+// def f2[M[_], T](x: M[T]) = x match { case Foo(y) => y }
+// ^
+// one warning found \ No newline at end of file
diff --git a/test/files/pos/t5041.scala b/test/files/pos/t5041.scala
new file mode 100644
index 0000000000..78a1b27d5a
--- /dev/null
+++ b/test/files/pos/t5041.scala
@@ -0,0 +1,9 @@
+case class Token(text: String, startIndex: Int)
+
+object Comment {
+ def unapply(s: String): Option[Token] = None
+}
+
+object HiddenTokens {
+ "foo" match { case Comment(_) => }
+}
diff --git a/test/files/run/t5428.check b/test/files/run/t5428.check
new file mode 100644
index 0000000000..7b4b1d6558
--- /dev/null
+++ b/test/files/run/t5428.check
@@ -0,0 +1 @@
+Stack(8, 7, 6, 5, 4, 3) \ No newline at end of file
diff --git a/test/files/run/t5428.scala b/test/files/run/t5428.scala
new file mode 100644
index 0000000000..106bb7fc31
--- /dev/null
+++ b/test/files/run/t5428.scala
@@ -0,0 +1,29 @@
+
+
+
+import collection.mutable.{Stack, StackProxy}
+
+
+
+class A extends StackProxy[Int] {
+ val self = Stack[Int]()
+}
+
+
+object Test {
+
+ def main(args: Array[String]) {
+ val a = new A
+
+ a push 3
+ a push 4
+ a push 5
+
+ a.push(6, 7, 8)
+
+ println(a)
+
+ a pop
+ }
+
+}