diff options
-rw-r--r-- | bincompat-forward.whitelist.conf | 4 | ||||
-rw-r--r-- | build.number | 2 | ||||
-rw-r--r-- | src/build/maven/maven-deploy.xml | 6 | ||||
-rw-r--r-- | src/compiler/scala/reflect/macros/runtime/Typers.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 9 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala | 6 | ||||
-rw-r--r-- | src/compiler/scala/tools/reflect/ToolBoxFactory.scala | 2 | ||||
-rw-r--r-- | src/library/scala/concurrent/impl/Promise.scala | 85 | ||||
-rw-r--r-- | src/library/scala/util/Properties.scala | 16 | ||||
-rw-r--r-- | test/files/neg/t7473.check | 7 | ||||
-rw-r--r-- | test/files/neg/t7473.scala | 7 | ||||
-rw-r--r-- | test/files/pos/lub-dealias-widen.scala | 34 | ||||
-rw-r--r-- | test/files/pos/t7461.check | 0 | ||||
-rw-r--r-- | test/files/pos/t7461/Macros_1.scala | 13 | ||||
-rw-r--r-- | test/files/pos/t7461/Test_2.scala | 3 |
15 files changed, 133 insertions, 63 deletions
diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index fd6451d3bc..83864f48ee 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -467,6 +467,10 @@ filter { { matchName="scala.concurrent.forkjoin.ForkJoinPool.helpJoinOnce" problemName=IncompatibleResultTypeProblem + }, + { + matchName="scala.concurrent.impl.Promise$CompletionLatch" + problemName=MissingClassProblem } ] } diff --git a/build.number b/build.number index 0b06d13468..d5dd553362 100644 --- a/build.number +++ b/build.number @@ -1,7 +1,7 @@ #Tue Sep 11 19:21:09 CEST 2007 version.major=2 version.minor=10 -version.patch=2 +version.patch=3 # This is the -N part of a version. if it's 0, it's dropped from maven versions. version.bnum=0 diff --git a/src/build/maven/maven-deploy.xml b/src/build/maven/maven-deploy.xml index bd946bf0f3..e70173319e 100644 --- a/src/build/maven/maven-deploy.xml +++ b/src/build/maven/maven-deploy.xml @@ -164,11 +164,7 @@ <attribute name="repository" /> <attribute name="version" /> <sequential> - <deploy-remote name="scala-library" version="@{version}" repository="@{repository}"> - <extra-attachments> - <artifact:attach type="jar" file="scala-library/scala-library-docs.jar" classifier="javadoc" /> - </extra-attachments> - </deploy-remote> + <deploy-remote name="scala-library" version="@{version}" repository="@{repository}"/> <deploy-remote name="jline" version="@{version}" repository="@{repository}"/> <deploy-remote name="scala-reflect" version="@{version}" repository="@{repository}"/> <deploy-remote name="scala-compiler" version="@{version}" repository="@{repository}" /> diff --git a/src/compiler/scala/reflect/macros/runtime/Typers.scala b/src/compiler/scala/reflect/macros/runtime/Typers.scala index 4d333f180b..a51bee0fe8 100644 --- a/src/compiler/scala/reflect/macros/runtime/Typers.scala +++ b/src/compiler/scala/reflect/macros/runtime/Typers.scala @@ -22,7 +22,7 @@ trait Typers { // typechecking uses silent anyways (e.g. in typedSelect), so you'll only waste your time // I'd advise fixing the root cause: finding why the context is not set to report errors // (also see reflect.runtime.ToolBoxes.typeCheckExpr for a workaround that might work for you) - wrapper(callsiteTyper.silent(_.typed(tree, universe.analyzer.EXPRmode, pt)) match { + wrapper(callsiteTyper.silent(_.typed(tree, universe.analyzer.EXPRmode, pt), reportAmbiguousErrors = false) match { case universe.analyzer.SilentResultValue(result) => macroLogVerbose(result) result diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index b8791c15dc..50398824e1 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1474,8 +1474,9 @@ self => * }}} */ def postfixExpr(): Tree = { - val base = opstack - var top = prefixExpr() + val start = in.offset + val base = opstack + var top = prefixExpr() while (isIdent) { top = reduceStack(isExpr = true, base, top, precedence(in.name), leftAssoc = treeInfo.isLeftAssoc(in.name)) @@ -1493,9 +1494,7 @@ self => val topinfo = opstack.head opstack = opstack.tail val od = stripParens(reduceStack(isExpr = true, base, topinfo.operand, 0, leftAssoc = true)) - return atPos(od.pos.startOrPoint, topinfo.offset) { - new PostfixSelect(od, topinfo.operator.encode) - } + return makePostfixSelect(start, topinfo.offset, od, topinfo.operator) } } reduceStack(isExpr = true, base, top, 0, leftAssoc = true) diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index b5771454f8..e92c3e1654 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -245,6 +245,12 @@ abstract class TreeBuilder { Assign(lhs, rhs) } + /** Tree for `od op`, start is start0 if od.pos is borked. */ + def makePostfixSelect(start0: Int, end: Int, od: Tree, op: Name): Tree = { + val start = if (od.pos.isDefined) od.pos.startOrPoint else start0 + atPos(r2p(start, end, end)) { new PostfixSelect(od, op.encode) } + } + /** A type tree corresponding to (possibly unary) intersection type */ def makeIntersectionTypeTree(tps: List[Tree]): Tree = if (tps.tail.isEmpty) tps.head diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 4b5dcadfa2..64b8870619 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -166,7 +166,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => transformDuringTyper(expr, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled)( (currentTyper, expr) => { trace("typing (implicit views = %s, macros = %s): ".format(!withImplicitViewsDisabled, !withMacrosDisabled))(showAttributed(expr, true, true, settings.Yshowsymkinds.value)) - currentTyper.silent(_.typed(expr, analyzer.EXPRmode, pt)) match { + currentTyper.silent(_.typed(expr, analyzer.EXPRmode, pt), reportAmbiguousErrors = false) match { case analyzer.SilentResultValue(result) => trace("success: ")(showAttributed(result, true, true, settings.Yshowsymkinds.value)) result diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala index 52f1075137..ed4039e2a5 100644 --- a/src/library/scala/concurrent/impl/Promise.scala +++ b/src/library/scala/concurrent/impl/Promise.scala @@ -8,11 +8,14 @@ package scala.concurrent.impl -import scala.concurrent.{ ExecutionContext, CanAwait, OnCompleteRunnable, TimeoutException, ExecutionException } +import scala.concurrent.{ ExecutionContext, CanAwait, OnCompleteRunnable, TimeoutException, ExecutionException, blocking } +import scala.concurrent.Future.InternalCallbackExecutor import scala.concurrent.duration.{ Duration, Deadline, FiniteDuration, NANOSECONDS } import scala.annotation.tailrec import scala.util.control.NonFatal import scala.util.{ Try, Success, Failure } +import java.io.ObjectInputStream +import java.util.concurrent.locks.AbstractQueuedSynchronizer private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] { def future: this.type = this @@ -52,70 +55,69 @@ private[concurrent] object Promise { case e: Error => Failure(new ExecutionException("Boxed Error", e)) case t => Failure(t) } + + /* + * Inspired by: http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/locks/AbstractQueuedSynchronizer.java + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + private final class CompletionLatch[T] extends AbstractQueuedSynchronizer with (Try[T] => Unit) { + override protected def tryAcquireShared(ignored: Int): Int = if (getState != 0) 1 else -1 + override protected def tryReleaseShared(ignore: Int): Boolean = { + setState(1) + true + } + override def apply(ignored: Try[T]): Unit = releaseShared(1) + } + /** Default promise implementation. */ class DefaultPromise[T] extends AbstractPromise with Promise[T] { self => updateState(null, Nil) // Start at "No callbacks" - protected final def tryAwait(atMost: Duration): Boolean = { - @tailrec - def awaitUnsafe(deadline: Deadline, nextWait: FiniteDuration): Boolean = { - if (!isCompleted && nextWait > Duration.Zero) { - val ms = nextWait.toMillis - val ns = (nextWait.toNanos % 1000000l).toInt // as per object.wait spec - - synchronized { if (!isCompleted) wait(ms, ns) } - - awaitUnsafe(deadline, deadline.timeLeft) - } else - isCompleted - } - @tailrec - def awaitUnbounded(): Boolean = { - if (isCompleted) true - else { - synchronized { if (!isCompleted) wait() } - awaitUnbounded() - } - } - + protected final def tryAwait(atMost: Duration): Boolean = if (!isCompleted) { import Duration.Undefined + import scala.concurrent.Future.InternalCallbackExecutor atMost match { - case u if u eq Undefined => throw new IllegalArgumentException("cannot wait for Undefined period") - case Duration.Inf => awaitUnbounded - case Duration.MinusInf => isCompleted - case f: FiniteDuration => if (f > Duration.Zero) awaitUnsafe(f.fromNow, f) else isCompleted + case e if e eq Undefined => throw new IllegalArgumentException("cannot wait for Undefined period") + case Duration.Inf => + val l = new CompletionLatch[T]() + onComplete(l)(InternalCallbackExecutor) + l.acquireSharedInterruptibly(1) + case Duration.MinusInf => // Drop out + case f: FiniteDuration => + if (f > Duration.Zero) { + val l = new CompletionLatch[T]() + onComplete(l)(InternalCallbackExecutor) + l.tryAcquireSharedNanos(1, f.toNanos) + } } - } + + isCompleted + } else true // Already completed @throws(classOf[TimeoutException]) @throws(classOf[InterruptedException]) def ready(atMost: Duration)(implicit permit: CanAwait): this.type = - if (isCompleted || tryAwait(atMost)) this + if (tryAwait(atMost)) this else throw new TimeoutException("Futures timed out after [" + atMost + "]") @throws(classOf[Exception]) def result(atMost: Duration)(implicit permit: CanAwait): T = - ready(atMost).value.get match { - case Failure(e) => throw e - case Success(r) => r - } + ready(atMost).value.get.get // ready throws TimeoutException if timeout so value.get is safe here def value: Option[Try[T]] = getState match { case c: Try[_] => Some(c.asInstanceOf[Try[T]]) case _ => None } - override def isCompleted: Boolean = getState match { // Cheaper than boxing result into Option due to "def value" - case _: Try[_] => true - case _ => false - } + override def isCompleted: Boolean = getState.isInstanceOf[Try[_]] def tryComplete(value: Try[T]): Boolean = { val resolved = resolveTry(value) - (try { - @tailrec + @tailrec def tryComplete(v: Try[T]): List[CallbackRunnable[T]] = { getState match { case raw: List[_] => @@ -124,10 +126,7 @@ private[concurrent] object Promise { case _ => null } } - tryComplete(resolved) - } finally { - synchronized { notifyAll() } //Notify any evil blockers - }) match { + tryComplete(resolved) match { case null => false case rs if rs.isEmpty => true case rs => rs.foreach(r => r.executeWithValue(resolved)); true diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala index cc145134c4..3cd6eb8659 100644 --- a/src/library/scala/util/Properties.scala +++ b/src/library/scala/util/Properties.scala @@ -72,7 +72,7 @@ private[scala] trait PropertiesTrait { * it is an RC, Beta, etc. or was built from source, or if the version * cannot be read. */ - val releaseVersion = + val releaseVersion = for { v <- scalaPropOrNone("maven.version.number") if !(v endsWith "-SNAPSHOT") @@ -86,7 +86,7 @@ private[scala] trait PropertiesTrait { * @return Some(version) if this is a non-final version, None if this * is a final release or the version cannot be read. */ - val developmentVersion = + val developmentVersion = for { v <- scalaPropOrNone("maven.version.number") if v endsWith "-SNAPSHOT" @@ -119,8 +119,7 @@ private[scala] trait PropertiesTrait { */ def lineSeparator = propOrElse("line.separator", "\n") - /** Various well-known properties. - */ + /* Various well-known properties. */ def javaClassPath = propOrEmpty("java.class.path") def javaHome = propOrEmpty("java.home") def javaVendor = propOrEmpty("java.vendor") @@ -136,10 +135,13 @@ private[scala] trait PropertiesTrait { def userHome = propOrEmpty("user.home") def userName = propOrEmpty("user.name") - /** Some derived values. - */ + /* Some derived values. */ + /** Returns `true` iff the underlying operating system is a version of Microsoft Windows. */ def isWin = osName startsWith "Windows" - def isMac = javaVendor startsWith "Apple" + // See http://mail.openjdk.java.net/pipermail/macosx-port-dev/2012-November/005148.html for + // the reason why we don't follow developer.apple.com/library/mac/#technotes/tn2002/tn2110. + /** Returns `true` iff the underlying operating system is a version of Apple Mac OSX. */ + def isMac = osName startsWith "Mac OS X" // This is looking for javac, tools.jar, etc. // Tries JDK_HOME first, then the more common but likely jre JAVA_HOME, diff --git a/test/files/neg/t7473.check b/test/files/neg/t7473.check new file mode 100644 index 0000000000..bc8c29d463 --- /dev/null +++ b/test/files/neg/t7473.check @@ -0,0 +1,7 @@ +t7473.scala:6: error: '<-' expected but '=' found. + (for (x = Option(i); if x == j) yield 42) toList + ^ +t7473.scala:6: error: illegal start of simple expression + (for (x = Option(i); if x == j) yield 42) toList + ^ +two errors found diff --git a/test/files/neg/t7473.scala b/test/files/neg/t7473.scala new file mode 100644 index 0000000000..593231d5f2 --- /dev/null +++ b/test/files/neg/t7473.scala @@ -0,0 +1,7 @@ + +object Foo { + val i,j = 3 + //for (x = Option(i); if x == j) yield 42 //t7473.scala:4: error: '<-' expected but '=' found. + // evil postfix! + (for (x = Option(i); if x == j) yield 42) toList +} diff --git a/test/files/pos/lub-dealias-widen.scala b/test/files/pos/lub-dealias-widen.scala new file mode 100644 index 0000000000..38854fbc5c --- /dev/null +++ b/test/files/pos/lub-dealias-widen.scala @@ -0,0 +1,34 @@ +import scala.language.higherKinds + +sealed trait Path { + type EncodeFunc + type Route[R] = List[String] => R + + def >>(f: Route[Int]): Sitelet[EncodeFunc] = ??? +} + +case object PAny extends Path { + type EncodeFunc = List[String] => String +} + +case class PLit[Next <: Path]() extends Path { + type EncodeFunc = Next#EncodeFunc +} + +trait Sitelet[EncodeFunc] { self => + def &[G <: H, H >: EncodeFunc](that: Sitelet[G]): Sitelet[H] = ??? +} + +object Test { + val r: Sitelet[Int => (Int => String)] = ??? + + val p2: PLit[PAny.type] = ??? + val r2 /*: Sitelet[List[String] => String] */ // annotate type and it compiles with 2.10.0 + = p2 >> { (xs: List[String]) => 0 } + + // This works after https://github.com/scala/scala/commit/a06d31f6a + // Before: error: inferred type arguments [List[String] => String,List[String] => String] + // do not conform to method &'s type parameter bounds + // [G <: H,H >: Int => (Int => String)] + val s = r & r2 +}
\ No newline at end of file diff --git a/test/files/pos/t7461.check b/test/files/pos/t7461.check new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/files/pos/t7461.check diff --git a/test/files/pos/t7461/Macros_1.scala b/test/files/pos/t7461/Macros_1.scala new file mode 100644 index 0000000000..353dec66d7 --- /dev/null +++ b/test/files/pos/t7461/Macros_1.scala @@ -0,0 +1,13 @@ +import scala.reflect.macros.Context +import language.experimental.macros + +object Macros { + def impl(c: Context) = { + import c.universe._ + val wut = c.typeCheck(Select(Literal(Constant(10)), newTermName("$minus")), silent = true) + // println(showRaw(wut, printIds = true, printTypes = true)) + c.literalUnit + } + + def foo = macro impl +}
\ No newline at end of file diff --git a/test/files/pos/t7461/Test_2.scala b/test/files/pos/t7461/Test_2.scala new file mode 100644 index 0000000000..3839659c9a --- /dev/null +++ b/test/files/pos/t7461/Test_2.scala @@ -0,0 +1,3 @@ +class C { + def foo = Macros.foo +}
\ No newline at end of file |