diff options
55 files changed, 429 insertions, 1415 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/collection/package.scala b/src/library/scala/collection/package.scala index 237ca28018..ac5cb66942 100644 --- a/src/library/scala/collection/package.scala +++ b/src/library/scala/collection/package.scala @@ -45,7 +45,7 @@ package scala * * The most common way to create a collection is to use the companion objects as factories. * Of these, the three most common - * are [[scala.collection.immutable.Seq]], [[scala.collection.immutable.Set]], and [[scala.collection.immutable.Map]]. Their + * are [[scala.collection.Seq]], [[scala.collection.immutable.Set]], and [[scala.collection.immutable.Map]]. Their * companion objects are all available * as type aliases the either the [[scala]] package or in `scala.Predef`, and can be used * like so: @@ -61,7 +61,7 @@ package scala * }}} * * It is also typical to use the [[scala.collection.immutable]] collections over those - * in [[scala.collection.mutable]]; The types aliased in the [[scala]] package and + * in [[scala.collection.mutable]]; The types aliased in * the `scala.Predef` object are the immutable versions. * * Also note that the collections library was carefully designed to include several implementations of 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/t4818.check b/test/files/neg/t4818.check new file mode 100644 index 0000000000..a5e15e456b --- /dev/null +++ b/test/files/neg/t4818.check @@ -0,0 +1,6 @@ +t4818.scala:4: error: type mismatch; + found : Int(5) + required: Nothing + def f(x: Any) = x match { case Fn(f) => f(5) } + ^ +one error found diff --git a/test/files/neg/t4818.scala b/test/files/neg/t4818.scala new file mode 100644 index 0000000000..faae229206 --- /dev/null +++ b/test/files/neg/t4818.scala @@ -0,0 +1,7 @@ +object Test { + case class Fn[A, B](f: A => B) + + def f(x: Any) = x match { case Fn(f) => f(5) } + + Fn((x: String) => x) +} 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 + } + +} |