From 0288a0788ae1ffbe9064992f1ac02f647bb64c17 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 17 Feb 2012 13:57:06 -0800 Subject: Fix for "type _$1 defined twice". Actually not a fix, only a workaround. Package objects strike again: you don't want to have existentials in there, like this: private val resolverFunction: PartialFunction[Throwable, Try[_]] = ... There are a few irrelevant-to-that-bug changes included which I did while debugging and figured I'd keep them. With this patch I can merge/am merging the scala.concurrent work. --- build.xml | 2 + .../scala/tools/nsc/ast/parser/Parsers.scala | 2 +- .../scala/tools/nsc/typechecker/Typers.scala | 4 + .../scala/concurrent/ConcurrentPackageObject.scala | 103 +++++++++++++++++++++ src/library/scala/concurrent/impl/Future.scala | 24 +++-- src/library/scala/concurrent/impl/Promise.scala | 1 + src/library/scala/concurrent/impl/package.scala | 39 -------- src/library/scala/concurrent/package.scala | 103 +-------------------- 8 files changed, 134 insertions(+), 144 deletions(-) create mode 100644 src/library/scala/concurrent/ConcurrentPackageObject.scala delete mode 100644 src/library/scala/concurrent/impl/package.scala diff --git a/build.xml b/build.xml index 79b36fd4a6..314ce379e1 100644 --- a/build.xml +++ b/build.xml @@ -1535,6 +1535,7 @@ DOCUMENTATION docUncompilable="${src.dir}/library-aux" sourcepath="${src.dir}" classpathref="pack.classpath" + addparams="${scalac.args.all}" docRootContent="${src.dir}/library/rootdoc.txt"> @@ -1620,6 +1621,7 @@ DOCUMENTATION classpathref="pack.classpath" srcdir="${src.dir}/compiler" docRootContent="${src.dir}/compiler/rootdoc.txt"> + addparams="${scalac.args.all}" diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index fe6dcc9138..e3a59058a3 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1205,7 +1205,7 @@ self => */ def wildcardType(start: Int) = { val pname = freshTypeName("_$") - val t = atPos(start) { Ident(pname) } + val t = atPos(start)(Ident(pname)) val bounds = typeBounds() val param = atPos(t.pos union bounds.pos) { makeSyntheticTypeParam(pname, bounds) } placeholderTypes = param :: placeholderTypes diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 23fc30b9fb..e7cd139ce0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2169,6 +2169,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // error for this is issued in RefChecks.checkDefaultsInOverloaded if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefaultFlag && !e.sym.hasAnnotation(BridgeClass) && !e1.sym.hasAnnotation(BridgeClass)) { + log("Double definition detected:\n " + + ((e.sym.getClass, e.sym.info, e.sym.ownerChain)) + "\n " + + ((e1.sym.getClass, e1.sym.info, e1.sym.ownerChain))) + DefDefinedTwiceError(e.sym, e1.sym) scope.unlink(e1) // need to unlink to avoid later problems with lub; see #2779 } diff --git a/src/library/scala/concurrent/ConcurrentPackageObject.scala b/src/library/scala/concurrent/ConcurrentPackageObject.scala new file mode 100644 index 0000000000..6aacd53de2 --- /dev/null +++ b/src/library/scala/concurrent/ConcurrentPackageObject.scala @@ -0,0 +1,103 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.concurrent + +import scala.util.{ Duration, Try, Success, Failure } +import ConcurrentPackageObject._ + +/** This package object contains primitives for concurrent and parallel programming. + */ +abstract class ConcurrentPackageObject { + /** A global execution environment for executing lightweight tasks. + */ + lazy val executionContext = + new impl.ExecutionContextImpl(java.util.concurrent.Executors.newCachedThreadPool()) + + /** A global service for scheduling tasks for execution. + */ + // lazy val scheduler = + // new default.SchedulerImpl + + val handledFutureException: PartialFunction[Throwable, Throwable] = { + case t: Throwable if isFutureThrowable(t) => t + } + + // TODO rename appropriately and make public + private[concurrent] def isFutureThrowable(t: Throwable) = t match { + case e: Error => false + case t: scala.util.control.ControlThrowable => false + case i: InterruptedException => false + case _ => true + } + + private[concurrent] def resolve[T](source: Try[T]): Try[T] = source match { + case Failure(t: scala.runtime.NonLocalReturnControl[_]) => Success(t.value.asInstanceOf[T]) + case Failure(t: scala.util.control.ControlThrowable) => Failure(new ExecutionException("Boxed ControlThrowable", t)) + case Failure(t: InterruptedException) => Failure(new ExecutionException("Boxed InterruptedException", t)) + case Failure(e: Error) => Failure(new ExecutionException("Boxed Error", e)) + case _ => source + } + + private[concurrent] def resolver[T] = + resolverFunction.asInstanceOf[PartialFunction[Throwable, Try[T]]] + + /* concurrency constructs */ + + def future[T](body: =>T)(implicit execCtx: ExecutionContext = executionContext): Future[T] = + execCtx future body + + def promise[T]()(implicit execCtx: ExecutionContext = executionContext): Promise[T] = + execCtx promise + + /** Wraps a block of code into an awaitable object. */ + def body2awaitable[T](body: =>T) = new Awaitable[T] { + def await(atMost: Duration)(implicit cb: CanAwait) = body + } + + /** Used to block on a piece of code which potentially blocks. + * + * @param body A piece of code which contains potentially blocking or long running calls. + * + * Calling this method may throw the following exceptions: + * - CancellationException - if the computation was cancelled + * - InterruptedException - in the case that a wait within the blockable object was interrupted + * - TimeoutException - in the case that the blockable object timed out + */ + def blocking[T](atMost: Duration)(body: =>T)(implicit execCtx: ExecutionContext): T = + executionContext.blocking(atMost)(body) + + /** Blocks on an awaitable object. + * + * @param awaitable An object with a `block` method which runs potentially blocking or long running calls. + * + * Calling this method may throw the following exceptions: + * - CancellationException - if the computation was cancelled + * - InterruptedException - in the case that a wait within the blockable object was interrupted + * - TimeoutException - in the case that the blockable object timed out + */ + def blocking[T](awaitable: Awaitable[T], atMost: Duration)(implicit execCtx: ExecutionContext = executionContext): T = + executionContext.blocking(awaitable, atMost) + + @inline implicit final def int2durationops(x: Int): DurationOps = new DurationOps(x) +} + +private[concurrent] object ConcurrentPackageObject { + // TODO, docs, return type + // Note that having this in the package object led to failures when + // compiling a subset of sources; it seems that the wildcard is not + // properly handled, and you get messages like "type _$1 defined twice". + // This is consistent with other package object breakdowns. + private val resolverFunction: PartialFunction[Throwable, Try[_]] = { + case t: scala.runtime.NonLocalReturnControl[_] => Success(t.value) + case t: scala.util.control.ControlThrowable => Failure(new ExecutionException("Boxed ControlThrowable", t)) + case t: InterruptedException => Failure(new ExecutionException("Boxed InterruptedException", t)) + case e: Error => Failure(new ExecutionException("Boxed Error", e)) + case t => Failure(t) + } +} diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala index 3664241ec0..24d0258cc8 100644 --- a/src/library/scala/concurrent/impl/Future.scala +++ b/src/library/scala/concurrent/impl/Future.scala @@ -8,14 +8,10 @@ package scala.concurrent.impl - - import scala.concurrent.{Awaitable, ExecutionContext} import scala.util.{ Try, Success, Failure } //import scala.util.continuations._ - - trait Future[+T] extends scala.concurrent.Future[T] with Awaitable[T] { implicit def executor: ExecutionContextImpl @@ -50,7 +46,7 @@ trait Future[+T] extends scala.concurrent.Future[T] with Awaitable[T] { case f @ Failure(t) => p complete f.asInstanceOf[Try[T]] case Success(v) => p complete (try { - Success(boxedType(m.erasure).cast(v).asInstanceOf[T]) + Success(Future.boxedType(m.erasure).cast(v).asInstanceOf[T]) } catch { case e: ClassCastException ⇒ Failure(e) }) @@ -72,6 +68,22 @@ trait Future[+T] extends scala.concurrent.Future[T] with Awaitable[T] { } +object Future { + import java.{ lang => jl } + private val toBoxed = Map[Class[_], Class[_]]( + classOf[Boolean] -> classOf[jl.Boolean], + classOf[Byte] -> classOf[jl.Byte], + classOf[Char] -> classOf[jl.Character], + classOf[Short] -> classOf[jl.Short], + classOf[Int] -> classOf[jl.Integer], + classOf[Long] -> classOf[jl.Long], + classOf[Float] -> classOf[jl.Float], + classOf[Double] -> classOf[jl.Double], + classOf[Unit] -> classOf[scala.runtime.BoxedUnit] + ) - + def boxedType(c: Class[_]): Class[_] = { + if (c.isPrimitive) toBoxed(c) else c + } +} diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala index 3f9970b178..7ef76e1501 100644 --- a/src/library/scala/concurrent/impl/Promise.scala +++ b/src/library/scala/concurrent/impl/Promise.scala @@ -75,6 +75,7 @@ trait Promise[T] extends scala.concurrent.Promise[T] with Future[T] { object Promise { + def dur2long(dur: Duration): Long = if (dur.isFinite) dur.toNanos else Long.MaxValue def EmptyPending[T](): FState[T] = emptyPendingValue.asInstanceOf[FState[T]] diff --git a/src/library/scala/concurrent/impl/package.scala b/src/library/scala/concurrent/impl/package.scala deleted file mode 100644 index 72add73167..0000000000 --- a/src/library/scala/concurrent/impl/package.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.concurrent - - - -import java.{lang => jl} -import scala.util.Duration - - - -package object impl { - - private val toBoxed = Map[Class[_], Class[_]]( - classOf[Boolean] -> classOf[jl.Boolean], - classOf[Byte] -> classOf[jl.Byte], - classOf[Char] -> classOf[jl.Character], - classOf[Short] -> classOf[jl.Short], - classOf[Int] -> classOf[jl.Integer], - classOf[Long] -> classOf[jl.Long], - classOf[Float] -> classOf[jl.Float], - classOf[Double] -> classOf[jl.Double], - classOf[Unit] -> classOf[scala.runtime.BoxedUnit]) - - def boxedType(c: Class[_]): Class[_] = { - if (c.isPrimitive) toBoxed(c) else c - } - - def dur2long(dur: Duration): Long = if (dur.isFinite) dur.toNanos else Long.MaxValue - -} - - diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala index 0725332c5e..6a98fd50c2 100644 --- a/src/library/scala/concurrent/package.scala +++ b/src/library/scala/concurrent/package.scala @@ -8,98 +8,17 @@ package scala - - import scala.util.{ Duration, Try, Success, Failure } - - /** This package object contains primitives for concurrent and parallel programming. */ -package object concurrent { - +package object concurrent extends scala.concurrent.ConcurrentPackageObject { type ExecutionException = java.util.concurrent.ExecutionException type CancellationException = java.util.concurrent.CancellationException type TimeoutException = java.util.concurrent.TimeoutException - - /** A global execution environment for executing lightweight tasks. - */ - lazy val executionContext = - new impl.ExecutionContextImpl(java.util.concurrent.Executors.newCachedThreadPool()) - - /** A global service for scheduling tasks for execution. - */ - // lazy val scheduler = - // new default.SchedulerImpl - - val handledFutureException: PartialFunction[Throwable, Throwable] = { - case t: Throwable if isFutureThrowable(t) => t - } - - // TODO rename appropriately and make public - private[concurrent] def isFutureThrowable(t: Throwable) = t match { - case e: Error => false - case t: scala.util.control.ControlThrowable => false - case i: InterruptedException => false - case _ => true - } - - private[concurrent] def resolve[T](source: Try[T]): Try[T] = source match { - case Failure(t: scala.runtime.NonLocalReturnControl[_]) => Success(t.value.asInstanceOf[T]) - case Failure(t: scala.util.control.ControlThrowable) => Failure(new ExecutionException("Boxed ControlThrowable", t)) - case Failure(t: InterruptedException) => Failure(new ExecutionException("Boxed InterruptedException", t)) - case Failure(e: Error) => Failure(new ExecutionException("Boxed Error", e)) - case _ => source - } - - // TODO, docs, return type - private val resolverFunction: PartialFunction[Throwable, Try[_]] = { - case t: scala.runtime.NonLocalReturnControl[_] => Success(t.value) - case t: scala.util.control.ControlThrowable => Failure(new ExecutionException("Boxed ControlThrowable", t)) - case t: InterruptedException => Failure(new ExecutionException("Boxed InterruptedException", t)) - case e: Error => Failure(new ExecutionException("Boxed Error", e)) - case t => Failure(t) - } - - private[concurrent] def resolver[T] = resolverFunction.asInstanceOf[PartialFunction[Throwable, Try[T]]] - - /* concurrency constructs */ - - def future[T](body: =>T)(implicit execCtx: ExecutionContext = executionContext): Future[T] = - execCtx future body - - def promise[T]()(implicit execCtx: ExecutionContext = executionContext): Promise[T] = - execCtx promise - - /** Wraps a block of code into an awaitable object. */ - def body2awaitable[T](body: =>T) = new Awaitable[T] { - def await(atMost: Duration)(implicit cb: CanAwait) = body - } - - /** Used to block on a piece of code which potentially blocks. - * - * @param body A piece of code which contains potentially blocking or long running calls. - * - * Calling this method may throw the following exceptions: - * - CancellationException - if the computation was cancelled - * - InterruptedException - in the case that a wait within the blockable object was interrupted - * - TimeoutException - in the case that the blockable object timed out - */ - def blocking[T](atMost: Duration)(body: =>T)(implicit execCtx: ExecutionContext): T = - executionContext.blocking(atMost)(body) - - /** Blocks on an awaitable object. - * - * @param awaitable An object with a `block` method which runs potentially blocking or long running calls. - * - * Calling this method may throw the following exceptions: - * - CancellationException - if the computation was cancelled - * - InterruptedException - in the case that a wait within the blockable object was interrupted - * - TimeoutException - in the case that the blockable object timed out - */ - def blocking[T](awaitable: Awaitable[T], atMost: Duration)(implicit execCtx: ExecutionContext = executionContext): T = - executionContext.blocking(awaitable, atMost) - +} + +package concurrent { object await { def ready[T](atMost: Duration)(awaitable: Awaitable[T])(implicit execCtx: ExecutionContext = executionContext): Awaitable[T] = { try blocking(awaitable, atMost) @@ -119,16 +38,7 @@ package object concurrent { * some programs cannot be written without them (e.g. multiple client threads * cannot send requests to a server thread through regular promises and futures). */ - object nondeterministic { - } - - @inline implicit final def int2durationops(x: Int) = new DurationOps(x) - -} - - - -package concurrent { + object nondeterministic { } /** A timeout exception. * @@ -144,7 +54,4 @@ package concurrent { // TODO ADD OTHERS def ns = util.Duration.fromNanos(0) } - } - - -- cgit v1.2.3